diff options
| author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2010-10-15 03:53:52 -0400 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2010-10-15 06:00:56 -0400 |
| commit | c44f9f76d26c3b5158c65201d30e96393efe2fbd (patch) | |
| tree | ea66fc950cc090085f5242d8a8bcbed3ac2c0cd0 | |
| parent | 69ce8aa4925a54de192cf64e99abd294586c1984 (diff) | |
fbdev: sh_mobile_lcdc: make platform videomode table optional
Add a default 720p mode to the sh_mobile_lcdc driver to be used, when no
videomode is specified in the platform data. This can be used, e.g., with HDMI.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
| -rw-r--r-- | drivers/video/sh_mobile_hdmi.c | 3 | ||||
| -rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 73 |
2 files changed, 51 insertions, 25 deletions
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 4d6ab86e9518..94a94fde2c67 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
| @@ -1051,7 +1051,8 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
| 1051 | goto egetclk; | 1051 | goto egetclk; |
| 1052 | } | 1052 | } |
| 1053 | 1053 | ||
| 1054 | rate = sh_hdmi_clk_configure(hdmi, pdata->lcd_chan->lcd_cfg[0].pixclock); | 1054 | /* Some arbitrary relaxed pixclock just to get things started */ |
| 1055 | rate = sh_hdmi_clk_configure(hdmi, 37037); | ||
| 1055 | if (rate < 0) { | 1056 | if (rate < 0) { |
| 1056 | ret = rate; | 1057 | ret = rate; |
| 1057 | goto erate; | 1058 | goto erate; |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index d6e9ff512443..a777cb99739c 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
| @@ -54,6 +54,9 @@ static int lcdc_shared_regs[] = { | |||
| 54 | }; | 54 | }; |
| 55 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) | 55 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) |
| 56 | 56 | ||
| 57 | #define DEFAULT_XRES 1280 | ||
| 58 | #define DEFAULT_YRES 1024 | ||
| 59 | |||
| 57 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { | 60 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { |
| 58 | [LDDCKPAT1R] = 0x400, | 61 | [LDDCKPAT1R] = 0x400, |
| 59 | [LDDCKPAT2R] = 0x404, | 62 | [LDDCKPAT2R] = 0x404, |
| @@ -107,6 +110,23 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { | |||
| 107 | #define LDRCNTR_MRC 0x00000001 | 110 | #define LDRCNTR_MRC 0x00000001 |
| 108 | #define LDSR_MRS 0x00000100 | 111 | #define LDSR_MRS 0x00000100 |
| 109 | 112 | ||
| 113 | static const struct fb_videomode default_720p = { | ||
| 114 | .name = "HDMI 720p", | ||
| 115 | .xres = 1280, | ||
| 116 | .yres = 720, | ||
| 117 | |||
| 118 | .left_margin = 200, | ||
| 119 | .right_margin = 88, | ||
| 120 | .hsync_len = 48, | ||
| 121 | |||
| 122 | .upper_margin = 20, | ||
| 123 | .lower_margin = 5, | ||
| 124 | .vsync_len = 5, | ||
| 125 | |||
| 126 | .pixclock = 13468, | ||
| 127 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, | ||
| 128 | }; | ||
| 129 | |||
| 110 | struct sh_mobile_lcdc_priv { | 130 | struct sh_mobile_lcdc_priv { |
| 111 | void __iomem *base; | 131 | void __iomem *base; |
| 112 | int irq; | 132 | int irq; |
| @@ -1045,7 +1065,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
| 1045 | struct fb_info *info = event->info; | 1065 | struct fb_info *info = event->info; |
| 1046 | struct sh_mobile_lcdc_chan *ch = info->par; | 1066 | struct sh_mobile_lcdc_chan *ch = info->par; |
| 1047 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; | 1067 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; |
| 1048 | struct fb_var_screeninfo *var; | ||
| 1049 | int ret; | 1068 | int ret; |
| 1050 | 1069 | ||
| 1051 | if (&ch->lcdc->notifier != nb) | 1070 | if (&ch->lcdc->notifier != nb) |
| @@ -1064,8 +1083,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
| 1064 | sh_mobile_lcdc_stop(ch->lcdc); | 1083 | sh_mobile_lcdc_stop(ch->lcdc); |
| 1065 | break; | 1084 | break; |
| 1066 | case FB_EVENT_RESUME: | 1085 | case FB_EVENT_RESUME: |
| 1067 | var = &info->var; | ||
| 1068 | |||
| 1069 | mutex_lock(&ch->open_lock); | 1086 | mutex_lock(&ch->open_lock); |
| 1070 | sh_mobile_fb_reconfig(info); | 1087 | sh_mobile_fb_reconfig(info); |
| 1071 | mutex_unlock(&ch->open_lock); | 1088 | mutex_unlock(&ch->open_lock); |
| @@ -1091,7 +1108,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1091 | struct fb_info *info; | 1108 | struct fb_info *info; |
| 1092 | struct sh_mobile_lcdc_priv *priv; | 1109 | struct sh_mobile_lcdc_priv *priv; |
| 1093 | struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; | 1110 | struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; |
| 1094 | struct sh_mobile_lcdc_chan_cfg *cfg; | ||
| 1095 | struct resource *res; | 1111 | struct resource *res; |
| 1096 | int error; | 1112 | int error; |
| 1097 | void *buf; | 1113 | void *buf; |
| @@ -1177,11 +1193,11 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1177 | struct fb_var_screeninfo *var; | 1193 | struct fb_var_screeninfo *var; |
| 1178 | const struct fb_videomode *lcd_cfg, *max_cfg = NULL; | 1194 | const struct fb_videomode *lcd_cfg, *max_cfg = NULL; |
| 1179 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 1195 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
| 1196 | struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; | ||
| 1197 | const struct fb_videomode *mode = cfg->lcd_cfg; | ||
| 1180 | unsigned long max_size = 0; | 1198 | unsigned long max_size = 0; |
| 1181 | int k; | 1199 | int k; |
| 1182 | 1200 | ||
| 1183 | cfg = &ch->cfg; | ||
| 1184 | |||
| 1185 | ch->info = framebuffer_alloc(0, &pdev->dev); | 1201 | ch->info = framebuffer_alloc(0, &pdev->dev); |
| 1186 | if (!ch->info) { | 1202 | if (!ch->info) { |
| 1187 | dev_err(&pdev->dev, "unable to allocate fb_info\n"); | 1203 | dev_err(&pdev->dev, "unable to allocate fb_info\n"); |
| @@ -1192,20 +1208,12 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1192 | info = ch->info; | 1208 | info = ch->info; |
| 1193 | var = &info->var; | 1209 | var = &info->var; |
| 1194 | info->fbops = &sh_mobile_lcdc_ops; | 1210 | info->fbops = &sh_mobile_lcdc_ops; |
| 1211 | info->par = ch; | ||
| 1195 | 1212 | ||
| 1196 | mutex_init(&ch->open_lock); | 1213 | mutex_init(&ch->open_lock); |
| 1197 | 1214 | ||
| 1198 | fb_videomode_to_var(var, &cfg->lcd_cfg[0]); | 1215 | for (k = 0, lcd_cfg = mode; |
| 1199 | /* Default Y virtual resolution is 2x panel size */ | 1216 | k < cfg->num_cfg && lcd_cfg; |
| 1200 | var->yres_virtual = var->yres * 2; | ||
| 1201 | var->activate = FB_ACTIVATE_NOW; | ||
| 1202 | |||
| 1203 | error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); | ||
| 1204 | if (error) | ||
| 1205 | break; | ||
| 1206 | |||
| 1207 | for (k = 0, lcd_cfg = cfg->lcd_cfg; | ||
| 1208 | k < cfg->num_cfg; | ||
| 1209 | k++, lcd_cfg++) { | 1217 | k++, lcd_cfg++) { |
| 1210 | unsigned long size = lcd_cfg->yres * lcd_cfg->xres; | 1218 | unsigned long size = lcd_cfg->yres * lcd_cfg->xres; |
| 1211 | 1219 | ||
| @@ -1215,13 +1223,27 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1215 | } | 1223 | } |
| 1216 | } | 1224 | } |
| 1217 | 1225 | ||
| 1218 | dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n", | 1226 | if (!mode) |
| 1219 | max_cfg->xres, max_cfg->yres); | 1227 | max_size = DEFAULT_XRES * DEFAULT_YRES; |
| 1228 | else if (max_cfg) | ||
| 1229 | dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n", | ||
| 1230 | max_cfg->xres, max_cfg->yres); | ||
| 1220 | 1231 | ||
| 1221 | info->fix = sh_mobile_lcdc_fix; | 1232 | info->fix = sh_mobile_lcdc_fix; |
| 1222 | info->fix.line_length = cfg->lcd_cfg[0].xres * (cfg->bpp / 8); | ||
| 1223 | info->fix.smem_len = max_size * (cfg->bpp / 8) * 2; | 1233 | info->fix.smem_len = max_size * (cfg->bpp / 8) * 2; |
| 1224 | 1234 | ||
| 1235 | if (!mode) | ||
| 1236 | mode = &default_720p; | ||
| 1237 | |||
| 1238 | fb_videomode_to_var(var, mode); | ||
| 1239 | /* Default Y virtual resolution is 2x panel size */ | ||
| 1240 | var->yres_virtual = var->yres * 2; | ||
| 1241 | var->activate = FB_ACTIVATE_NOW; | ||
| 1242 | |||
| 1243 | error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); | ||
| 1244 | if (error) | ||
| 1245 | break; | ||
| 1246 | |||
| 1225 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, | 1247 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, |
| 1226 | &ch->dma_handle, GFP_KERNEL); | 1248 | &ch->dma_handle, GFP_KERNEL); |
| 1227 | if (!buf) { | 1249 | if (!buf) { |
| @@ -1242,9 +1264,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1242 | } | 1264 | } |
| 1243 | 1265 | ||
| 1244 | info->fix.smem_start = ch->dma_handle; | 1266 | info->fix.smem_start = ch->dma_handle; |
| 1267 | info->fix.line_length = var->xres * (cfg->bpp / 8); | ||
| 1245 | info->screen_base = buf; | 1268 | info->screen_base = buf; |
| 1246 | info->device = &pdev->dev; | 1269 | info->device = &pdev->dev; |
| 1247 | info->par = ch; | ||
| 1248 | ch->display_var = *var; | 1270 | ch->display_var = *var; |
| 1249 | } | 1271 | } |
| 1250 | 1272 | ||
| @@ -1259,6 +1281,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1259 | 1281 | ||
| 1260 | for (i = 0; i < j; i++) { | 1282 | for (i = 0; i < j; i++) { |
| 1261 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 1283 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
| 1284 | const struct fb_videomode *mode = ch->cfg.lcd_cfg; | ||
| 1285 | |||
| 1286 | if (!mode) | ||
| 1287 | mode = &default_720p; | ||
| 1262 | 1288 | ||
| 1263 | info = ch->info; | 1289 | info = ch->info; |
| 1264 | 1290 | ||
| @@ -1271,7 +1297,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1271 | } | 1297 | } |
| 1272 | } | 1298 | } |
| 1273 | 1299 | ||
| 1274 | fb_videomode_to_modelist(ch->cfg.lcd_cfg, ch->cfg.num_cfg, &info->modelist); | 1300 | fb_videomode_to_modelist(mode, ch->cfg.num_cfg, &info->modelist); |
| 1275 | error = register_framebuffer(info); | 1301 | error = register_framebuffer(info); |
| 1276 | if (error < 0) | 1302 | if (error < 0) |
| 1277 | goto err1; | 1303 | goto err1; |
| @@ -1281,8 +1307,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1281 | pdev->name, | 1307 | pdev->name, |
| 1282 | (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? | 1308 | (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? |
| 1283 | "mainlcd" : "sublcd", | 1309 | "mainlcd" : "sublcd", |
| 1284 | (int) ch->cfg.lcd_cfg[0].xres, | 1310 | info->var.xres, info->var.yres, |
| 1285 | (int) ch->cfg.lcd_cfg[0].yres, | ||
| 1286 | ch->cfg.bpp); | 1311 | ch->cfg.bpp); |
| 1287 | 1312 | ||
| 1288 | /* deferred io mode: disable clock to save power */ | 1313 | /* deferred io mode: disable clock to save power */ |
