Merge branch 'common/fbdev' of master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6

This commit is contained in:
Paul Mundt 2010-11-10 18:34:49 +09:00
commit 12ddf37444
3 changed files with 128 additions and 86 deletions

View File

@ -209,7 +209,8 @@ enum hotplug_state {
struct sh_hdmi { struct sh_hdmi {
void __iomem *base; void __iomem *base;
enum hotplug_state hp_state; /* hot-plug status */ enum hotplug_state hp_state; /* hot-plug status */
bool preprogrammed_mode; /* use a pre-programmed VIC or the external mode */ u8 preprogrammed_vic; /* use a pre-programmed VIC or
the external mode */
struct clk *hdmi_clk; struct clk *hdmi_clk;
struct device *dev; struct device *dev;
struct fb_info *info; struct fb_info *info;
@ -342,7 +343,7 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
/* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */ /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
if (!hdmi->preprogrammed_mode) if (!hdmi->preprogrammed_vic)
hdmi_write(hdmi, sync | 1 | (voffset << 4), hdmi_write(hdmi, sync | 1 | (voffset << 4),
HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
} }
@ -466,7 +467,18 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
*/ */
static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
{ {
if (hdmi->var.yres > 480) { if (hdmi->var.pixclock < 10000) {
/* for 1080p8bit 148MHz */
hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
} else if (hdmi->var.pixclock < 30000) {
/* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
/* /*
* [1:0] Speed_A * [1:0] Speed_A
@ -565,13 +577,11 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3); hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
/* /*
* VIC = 1280 x 720p: ignored if external config is used * VIC should be ignored if external config is used, so, we could just use 0,
* Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode * but play safe and use a valid value in any case just in case
*/ */
if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920) if (hdmi->preprogrammed_vic)
vic = 16; vic = hdmi->preprogrammed_vic;
else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
vic = 2;
else else
vic = 4; vic = 4;
hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4); hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
@ -685,11 +695,21 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
} }
static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
const struct fb_videomode *mode) const struct fb_videomode *mode,
unsigned long *hdmi_rate, unsigned long *parent_rate)
{ {
long target = PICOS2KHZ(mode->pixclock) * 1000, unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
rate = clk_round_rate(hdmi->hdmi_clk, target); struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
*hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
if ((long)*hdmi_rate < 0)
*hdmi_rate = clk_get_rate(hdmi->hdmi_clk);
rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX;
if (rate_error && pdata->clk_optimize_parent)
rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate);
else if (clk_get_parent(hdmi->hdmi_clk))
*parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk));
dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n", dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
mode->left_margin, mode->xres, mode->left_margin, mode->xres,
@ -697,14 +717,15 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
mode->upper_margin, mode->yres, mode->upper_margin, mode->yres,
mode->lower_margin, mode->vsync_len); mode->lower_margin, mode->vsync_len);
dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target, dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target,
rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0, rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
mode->refresh); mode->refresh, *parent_rate);
return rate_error; return rate_error;
} }
static int sh_hdmi_read_edid(struct sh_hdmi *hdmi) static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
unsigned long *parent_rate)
{ {
struct fb_var_screeninfo tmpvar; struct fb_var_screeninfo tmpvar;
struct fb_var_screeninfo *var = &tmpvar; struct fb_var_screeninfo *var = &tmpvar;
@ -754,11 +775,14 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
for (i = 0, mode = hdmi->monspec.modedb; for (i = 0, mode = hdmi->monspec.modedb;
f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match; f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
i++, mode++) { i++, mode++) {
unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode); unsigned long rate_error;
/* No interest in unmatching modes */ /* No interest in unmatching modes */
if (f_width != mode->xres || f_height != mode->yres) if (f_width != mode->xres || f_height != mode->yres)
continue; continue;
rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
/* /*
* Exact match if either the refresh rate matches or it * Exact match if either the refresh rate matches or it
@ -802,7 +826,7 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
if (modelist) { if (modelist) {
found = &modelist->mode; found = &modelist->mode;
found_rate_error = sh_hdmi_rate_error(hdmi, found); found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, parent_rate);
} }
} }
@ -810,16 +834,27 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
if (!found) if (!found)
return -ENXIO; return -ENXIO;
dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n", if (found->xres == 640 && found->yres == 480 && found->refresh == 60)
modelist ? "default" : "EDID", found->xres, found->yres, hdmi->preprogrammed_vic = 1;
found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error); else if (found->xres == 720 && found->yres == 480 && found->refresh == 60)
hdmi->preprogrammed_vic = 2;
if ((found->xres == 720 && found->yres == 480) || else if (found->xres == 720 && found->yres == 576 && found->refresh == 50)
(found->xres == 1280 && found->yres == 720) || hdmi->preprogrammed_vic = 17;
(found->xres == 1920 && found->yres == 1080)) else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60)
hdmi->preprogrammed_mode = true; hdmi->preprogrammed_vic = 4;
else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24)
hdmi->preprogrammed_vic = 32;
else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50)
hdmi->preprogrammed_vic = 31;
else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60)
hdmi->preprogrammed_vic = 16;
else else
hdmi->preprogrammed_mode = false; hdmi->preprogrammed_vic = 0;
dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
modelist ? "default" : "EDID", hdmi->preprogrammed_vic ? "VIC" : "external",
found->xres, found->yres, found->refresh,
PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
fb_videomode_to_var(&hdmi->var, found); fb_videomode_to_var(&hdmi->var, found);
sh_hdmi_external_video_param(hdmi); sh_hdmi_external_video_param(hdmi);
@ -972,39 +1007,37 @@ static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
/** /**
* sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
* @hdmi: driver context * @hdmi: driver context
* @pixclock: pixel clock period in picoseconds * @hdmi_rate: HDMI clock frequency in Hz
* return: configured positive rate if successful * @parent_rate: if != 0 - set parent clock rate for optimal precision
* 0 if couldn't set the rate, but managed to enable the clock * return: configured positive rate if successful
* negative error, if couldn't enable the clock * 0 if couldn't set the rate, but managed to enable the
* clock, negative error, if couldn't enable the clock
*/ */
static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock) static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
unsigned long parent_rate)
{ {
long rate;
int ret; int ret;
rate = PICOS2KHZ(pixclock) * 1000; if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) {
rate = clk_round_rate(hdmi->hdmi_clk, rate); ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate);
if (rate > 0) {
ret = clk_set_rate(hdmi->hdmi_clk, rate);
if (ret < 0) { if (ret < 0) {
dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret); dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret);
rate = 0; hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate);
} else { } else {
dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate); dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate);
} }
} else {
rate = 0;
dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
} }
ret = clk_enable(hdmi->hdmi_clk); ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate);
if (ret < 0) { if (ret < 0) {
dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret); dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret);
return ret; hdmi_rate = 0;
} else {
dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate);
} }
return rate; return hdmi_rate;
} }
/* Hotplug interrupt occurred, read EDID */ /* Hotplug interrupt occurred, read EDID */
@ -1024,16 +1057,17 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
mutex_lock(&hdmi->mutex); mutex_lock(&hdmi->mutex);
if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
unsigned long parent_rate = 0, hdmi_rate;
/* A device has been plugged in */ /* A device has been plugged in */
pm_runtime_get_sync(hdmi->dev); pm_runtime_get_sync(hdmi->dev);
ret = sh_hdmi_read_edid(hdmi); ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
if (ret < 0) if (ret < 0)
goto out; goto out;
/* Reconfigure the clock */ /* Reconfigure the clock */
clk_disable(hdmi->hdmi_clk); ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
if (ret < 0) if (ret < 0)
goto out; goto out;
@ -1071,6 +1105,10 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
if (!hdmi->info) if (!hdmi->info)
goto out; goto out;
hdmi->monspec.modedb_len = 0;
fb_destroy_modedb(hdmi->monspec.modedb);
hdmi->monspec.modedb = NULL;
acquire_console_sem(); acquire_console_sem();
/* HDMI disconnect */ /* HDMI disconnect */
@ -1078,7 +1116,6 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
release_console_sem(); release_console_sem();
pm_runtime_put(hdmi->dev); pm_runtime_put(hdmi->dev);
fb_destroy_modedb(hdmi->monspec.modedb);
} }
out: out:
@ -1163,13 +1200,22 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
goto egetclk; goto egetclk;
} }
/* Some arbitrary relaxed pixclock just to get things started */ /* An arbitrary relaxed pixclock just to get things started: from standard 480p */
rate = sh_hdmi_clk_configure(hdmi, 37037); rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
if (rate > 0)
rate = sh_hdmi_clk_configure(hdmi, rate, 0);
if (rate < 0) { if (rate < 0) {
ret = rate; ret = rate;
goto erate; goto erate;
} }
ret = clk_enable(hdmi->hdmi_clk);
if (ret < 0) {
dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
goto erate;
}
dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
@ -1187,10 +1233,6 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hdmi); platform_set_drvdata(pdev, hdmi);
/* Product and revision IDs are 0 in sh-mobile version */
dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
/* Set up LCDC callbacks */ /* Set up LCDC callbacks */
board_cfg = &pdata->lcd_chan->board_cfg; board_cfg = &pdata->lcd_chan->board_cfg;
board_cfg->owner = THIS_MODULE; board_cfg->owner = THIS_MODULE;
@ -1203,6 +1245,10 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_resume(&pdev->dev); pm_runtime_resume(&pdev->dev);
/* Product and revision IDs are 0 in sh-mobile version */
dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
ret = request_irq(irq, sh_hdmi_hotplug, 0, ret = request_irq(irq, sh_hdmi_hotplug, 0,
dev_name(&pdev->dev), hdmi); dev_name(&pdev->dev), hdmi);
if (ret < 0) { if (ret < 0) {

View File

@ -54,8 +54,8 @@ static int lcdc_shared_regs[] = {
}; };
#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
#define DEFAULT_XRES 1280 #define MAX_XRES 1920
#define DEFAULT_YRES 1024 #define MAX_YRES 1080
static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
[LDDCKPAT1R] = 0x400, [LDDCKPAT1R] = 0x400,
@ -115,15 +115,16 @@ static const struct fb_videomode default_720p = {
.xres = 1280, .xres = 1280,
.yres = 720, .yres = 720,
.left_margin = 200, .left_margin = 220,
.right_margin = 88, .right_margin = 110,
.hsync_len = 48, .hsync_len = 40,
.upper_margin = 20, .upper_margin = 20,
.lower_margin = 5, .lower_margin = 5,
.vsync_len = 5, .vsync_len = 5,
.pixclock = 13468, .pixclock = 13468,
.refresh = 60,
.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
}; };
@ -913,22 +914,12 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
{ {
struct sh_mobile_lcdc_chan *ch = info->par; struct sh_mobile_lcdc_chan *ch = info->par;
if (var->xres < 160 || var->xres > 1920 || if (var->xres > MAX_XRES || var->yres > MAX_YRES ||
var->yres < 120 || var->yres > 1080 ||
var->left_margin < 32 || var->left_margin > 320 ||
var->right_margin < 12 || var->right_margin > 240 ||
var->upper_margin < 12 || var->upper_margin > 120 ||
var->lower_margin < 1 || var->lower_margin > 64 ||
var->hsync_len < 32 || var->hsync_len > 240 ||
var->vsync_len < 2 || var->vsync_len > 64 ||
var->pixclock < 6000 || var->pixclock > 40000 ||
var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) { var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n", dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n",
var->xres, var->yres, var->left_margin, var->xres, var->right_margin, var->hsync_len,
var->left_margin, var->right_margin, var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
var->upper_margin, var->lower_margin, PICOS2KHZ(var->pixclock));
var->hsync_len, var->vsync_len,
var->pixclock);
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
@ -1197,6 +1188,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
const struct fb_videomode *mode = cfg->lcd_cfg; const struct fb_videomode *mode = cfg->lcd_cfg;
unsigned long max_size = 0; unsigned long max_size = 0;
int k; int k;
int num_cfg;
ch->info = framebuffer_alloc(0, &pdev->dev); ch->info = framebuffer_alloc(0, &pdev->dev);
if (!ch->info) { if (!ch->info) {
@ -1224,7 +1216,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
} }
if (!mode) if (!mode)
max_size = DEFAULT_XRES * DEFAULT_YRES; max_size = MAX_XRES * MAX_YRES;
else if (max_cfg) else if (max_cfg)
dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n", dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
max_cfg->xres, max_cfg->yres); max_cfg->xres, max_cfg->yres);
@ -1232,8 +1224,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
info->fix = sh_mobile_lcdc_fix; info->fix = sh_mobile_lcdc_fix;
info->fix.smem_len = max_size * (cfg->bpp / 8) * 2; info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
if (!mode) if (!mode) {
mode = &default_720p; mode = &default_720p;
num_cfg = 1;
} else {
num_cfg = ch->cfg.num_cfg;
}
fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
fb_videomode_to_var(var, mode); fb_videomode_to_var(var, mode);
/* Default Y virtual resolution is 2x panel size */ /* Default Y virtual resolution is 2x panel size */
@ -1281,10 +1279,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
for (i = 0; i < j; i++) { for (i = 0; i < j; i++) {
struct sh_mobile_lcdc_chan *ch = priv->ch + i; struct sh_mobile_lcdc_chan *ch = priv->ch + i;
const struct fb_videomode *mode = ch->cfg.lcd_cfg;
if (!mode)
mode = &default_720p;
info = ch->info; info = ch->info;
@ -1297,7 +1291,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
} }
} }
fb_videomode_to_modelist(mode, ch->cfg.num_cfg, &info->modelist);
error = register_framebuffer(info); error = register_framebuffer(info);
if (error < 0) if (error < 0)
goto err1; goto err1;

View File

@ -13,6 +13,7 @@
struct sh_mobile_lcdc_chan_cfg; struct sh_mobile_lcdc_chan_cfg;
struct device; struct device;
struct clk;
/* /*
* flags format * flags format
@ -33,6 +34,8 @@ struct sh_mobile_hdmi_info {
struct sh_mobile_lcdc_chan_cfg *lcd_chan; struct sh_mobile_lcdc_chan_cfg *lcd_chan;
struct device *lcd_dev; struct device *lcd_dev;
unsigned int flags; unsigned int flags;
long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
unsigned long *parent_freq);
}; };
#endif #endif