aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-06-29 07:13:07 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-06-29 07:13:07 -0400
commit974a65825e0b5fbda49605f0416a2c975d66e9e6 (patch)
tree72188f07c300e04f30d059bf502f651d2cbeb829
parent465698ee7bf457d1a3f35f0cb6e1e8fa144946f5 (diff)
parent6c6f510afb86e3c77c351dfa20cbb8ca834abad9 (diff)
Merge "Apply LCD manager related parameters" from Archit
The LCD interface drivers(DPI, DSI, RFBI, SDI) do some direct DISPC register writes to configure LCD manager related fields. This series groups these fields into a single struct, and let's the interface driver apply these parameters. This allows us to: - Check the LCD manager related parameters before applying them. - Remove some omap_dss_device references as APPLY holds the applied parameters. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/omap2/dss/apply.c85
-rw-r--r--drivers/video/omap2/dss/dispc.c26
-rw-r--r--drivers/video/omap2/dss/display.c34
-rw-r--r--drivers/video/omap2/dss/dpi.c31
-rw-r--r--drivers/video/omap2/dss/dsi.c91
-rw-r--r--drivers/video/omap2/dss/dss.h31
-rw-r--r--drivers/video/omap2/dss/manager.c35
-rw-r--r--drivers/video/omap2/dss/overlay.c13
-rw-r--r--drivers/video/omap2/dss/rfbi.c39
-rw-r--r--drivers/video/omap2/dss/sdi.c32
10 files changed, 271 insertions, 146 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 3ce7a3ec6224..0fefc68372b9 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -104,6 +104,7 @@ struct mgr_priv_data {
104 bool shadow_extra_info_dirty; 104 bool shadow_extra_info_dirty;
105 105
106 struct omap_video_timings timings; 106 struct omap_video_timings timings;
107 struct dss_lcd_mgr_config lcd_config;
107}; 108};
108 109
109static struct { 110static struct {
@@ -137,6 +138,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
137void dss_apply_init(void) 138void dss_apply_init(void)
138{ 139{
139 const int num_ovls = dss_feat_get_num_ovls(); 140 const int num_ovls = dss_feat_get_num_ovls();
141 struct mgr_priv_data *mp;
140 int i; 142 int i;
141 143
142 spin_lock_init(&data_lock); 144 spin_lock_init(&data_lock);
@@ -168,16 +170,35 @@ void dss_apply_init(void)
168 170
169 op->user_info = op->info; 171 op->user_info = op->info;
170 } 172 }
173
174 /*
175 * Initialize some of the lcd_config fields for TV manager, this lets
176 * us prevent checking if the manager is LCD or TV at some places
177 */
178 mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
179
180 mp->lcd_config.video_port_width = 24;
181 mp->lcd_config.clock_info.lck_div = 1;
182 mp->lcd_config.clock_info.pck_div = 1;
171} 183}
172 184
185/*
186 * A LCD manager's stallmode decides whether it is in manual or auto update. TV
187 * manager is always auto update, stallmode field for TV manager is false by
188 * default
189 */
173static bool ovl_manual_update(struct omap_overlay *ovl) 190static bool ovl_manual_update(struct omap_overlay *ovl)
174{ 191{
175 return ovl->manager->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 192 struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
193
194 return mp->lcd_config.stallmode;
176} 195}
177 196
178static bool mgr_manual_update(struct omap_overlay_manager *mgr) 197static bool mgr_manual_update(struct omap_overlay_manager *mgr)
179{ 198{
180 return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 199 struct mgr_priv_data *mp = get_mgr_priv(mgr);
200
201 return mp->lcd_config.stallmode;
181} 202}
182 203
183static int dss_check_settings_low(struct omap_overlay_manager *mgr, 204static int dss_check_settings_low(struct omap_overlay_manager *mgr,
@@ -214,7 +235,7 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr,
214 ois[ovl->id] = oi; 235 ois[ovl->id] = oi;
215 } 236 }
216 237
217 return dss_mgr_check(mgr, mi, &mp->timings, ois); 238 return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
218} 239}
219 240
220/* 241/*
@@ -550,7 +571,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
550 571
551 mp = get_mgr_priv(ovl->manager); 572 mp = get_mgr_priv(ovl->manager);
552 573
553 replication = dss_use_replication(ovl->manager->device, oi->color_mode); 574 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
554 575
555 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); 576 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings);
556 if (r) { 577 if (r) {
@@ -633,6 +654,24 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
633 654
634 dispc_mgr_set_timings(mgr->id, &mp->timings); 655 dispc_mgr_set_timings(mgr->id, &mp->timings);
635 656
657 /* lcd_config parameters */
658 if (dss_mgr_is_lcd(mgr->id)) {
659 dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
660
661 dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
662 dispc_mgr_enable_fifohandcheck(mgr->id,
663 mp->lcd_config.fifohandcheck);
664
665 dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
666
667 dispc_mgr_set_tft_data_lines(mgr->id,
668 mp->lcd_config.video_port_width);
669
670 dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
671
672 dispc_mgr_set_lcd_type_tft(mgr->id);
673 }
674
636 mp->extra_info_dirty = false; 675 mp->extra_info_dirty = false;
637 if (mp->updating) 676 if (mp->updating)
638 mp->shadow_extra_info_dirty = true; 677 mp->shadow_extra_info_dirty = true;
@@ -1292,6 +1331,44 @@ void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
1292 mutex_unlock(&apply_lock); 1331 mutex_unlock(&apply_lock);
1293} 1332}
1294 1333
1334static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1335 const struct dss_lcd_mgr_config *config)
1336{
1337 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1338
1339 mp->lcd_config = *config;
1340 mp->extra_info_dirty = true;
1341}
1342
1343void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1344 const struct dss_lcd_mgr_config *config)
1345{
1346 unsigned long flags;
1347 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1348
1349 mutex_lock(&apply_lock);
1350
1351 if (mp->enabled) {
1352 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
1353 mgr->name);
1354 goto out;
1355 }
1356
1357 spin_lock_irqsave(&data_lock, flags);
1358
1359 dss_apply_mgr_lcd_config(mgr, config);
1360
1361 dss_write_regs();
1362 dss_set_go_bits();
1363
1364 spin_unlock_irqrestore(&data_lock, flags);
1365
1366 wait_pending_extra_info_updates();
1367
1368out:
1369 mutex_unlock(&apply_lock);
1370}
1371
1295int dss_ovl_set_info(struct omap_overlay *ovl, 1372int dss_ovl_set_info(struct omap_overlay *ovl,
1296 struct omap_overlay_info *info) 1373 struct omap_overlay_info *info)
1297{ 1374{
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index d1a7a0c90289..5b289c5f695b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -498,16 +498,6 @@ void dispc_runtime_put(void)
498 WARN_ON(r < 0 && r != -ENOSYS); 498 WARN_ON(r < 0 && r != -ENOSYS);
499} 499}
500 500
501static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
502{
503 if (channel == OMAP_DSS_CHANNEL_LCD ||
504 channel == OMAP_DSS_CHANNEL_LCD2 ||
505 channel == OMAP_DSS_CHANNEL_LCD3)
506 return true;
507 else
508 return false;
509}
510
511u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) 501u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
512{ 502{
513 return mgr_desc[channel].vsync_irq; 503 return mgr_desc[channel].vsync_irq;
@@ -1010,7 +1000,7 @@ static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
1010{ 1000{
1011 u32 coef_r, coef_g, coef_b; 1001 u32 coef_r, coef_g, coef_b;
1012 1002
1013 if (!dispc_mgr_is_lcd(channel)) 1003 if (!dss_mgr_is_lcd(channel))
1014 return; 1004 return;
1015 1005
1016 coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | 1006 coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
@@ -1869,7 +1859,7 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
1869 1859
1870 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 1860 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1871 pclk = dispc_mgr_pclk_rate(channel); 1861 pclk = dispc_mgr_pclk_rate(channel);
1872 if (dispc_mgr_is_lcd(channel)) 1862 if (dss_mgr_is_lcd(channel))
1873 lclk = dispc_mgr_lclk_rate(channel); 1863 lclk = dispc_mgr_lclk_rate(channel);
1874 else 1864 else
1875 lclk = dispc_fclk_rate(); 1865 lclk = dispc_fclk_rate();
@@ -2452,7 +2442,7 @@ bool dispc_mgr_is_enabled(enum omap_channel channel)
2452 2442
2453void dispc_mgr_enable(enum omap_channel channel, bool enable) 2443void dispc_mgr_enable(enum omap_channel channel, bool enable)
2454{ 2444{
2455 if (dispc_mgr_is_lcd(channel)) 2445 if (dss_mgr_is_lcd(channel))
2456 dispc_mgr_enable_lcd_out(channel, enable); 2446 dispc_mgr_enable_lcd_out(channel, enable);
2457 else if (channel == OMAP_DSS_CHANNEL_DIGIT) 2447 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2458 dispc_mgr_enable_digit_out(enable); 2448 dispc_mgr_enable_digit_out(enable);
@@ -2642,7 +2632,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel,
2642 2632
2643 timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); 2633 timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
2644 2634
2645 if (dispc_mgr_is_lcd(channel)) 2635 if (dss_mgr_is_lcd(channel))
2646 timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw, 2636 timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw,
2647 timings->hfp, timings->hbp, 2637 timings->hfp, timings->hbp,
2648 timings->vsw, timings->vfp, 2638 timings->vsw, timings->vfp,
@@ -2734,7 +2724,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
2734 return; 2724 return;
2735 } 2725 }
2736 2726
2737 if (dispc_mgr_is_lcd(channel)) { 2727 if (dss_mgr_is_lcd(channel)) {
2738 _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw, 2728 _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
2739 t.vfp, t.vbp, t.vsync_level, t.hsync_level, 2729 t.vfp, t.vbp, t.vsync_level, t.hsync_level,
2740 t.data_pclk_edge, t.de_level, t.sync_pclk_edge); 2730 t.data_pclk_edge, t.de_level, t.sync_pclk_edge);
@@ -2840,7 +2830,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
2840{ 2830{
2841 unsigned long r; 2831 unsigned long r;
2842 2832
2843 if (dispc_mgr_is_lcd(channel)) { 2833 if (dss_mgr_is_lcd(channel)) {
2844 int pcd; 2834 int pcd;
2845 u32 l; 2835 u32 l;
2846 2836
@@ -3224,15 +3214,13 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3224 return 0; 3214 return 0;
3225} 3215}
3226 3216
3227int dispc_mgr_set_clock_div(enum omap_channel channel, 3217void dispc_mgr_set_clock_div(enum omap_channel channel,
3228 struct dispc_clock_info *cinfo) 3218 struct dispc_clock_info *cinfo)
3229{ 3219{
3230 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); 3220 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
3231 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); 3221 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
3232 3222
3233 dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); 3223 dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
3234
3235 return 0;
3236} 3224}
3237 3225
3238int dispc_mgr_get_clock_div(enum omap_channel channel, 3226int dispc_mgr_get_clock_div(enum omap_channel channel,
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 1a0c15f83d0d..5bd957e85505 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -316,40 +316,6 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
316} 316}
317EXPORT_SYMBOL(omapdss_default_get_timings); 317EXPORT_SYMBOL(omapdss_default_get_timings);
318 318
319/* Checks if replication logic should be used. Only use for active matrix,
320 * when overlay is in RGB12U or RGB16 mode, and LCD interface is
321 * 18bpp or 24bpp */
322bool dss_use_replication(struct omap_dss_device *dssdev,
323 enum omap_color_mode mode)
324{
325 int bpp;
326
327 if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
328 return false;
329
330 switch (dssdev->type) {
331 case OMAP_DISPLAY_TYPE_DPI:
332 bpp = dssdev->phy.dpi.data_lines;
333 break;
334 case OMAP_DISPLAY_TYPE_HDMI:
335 case OMAP_DISPLAY_TYPE_VENC:
336 case OMAP_DISPLAY_TYPE_SDI:
337 bpp = 24;
338 break;
339 case OMAP_DISPLAY_TYPE_DBI:
340 bpp = dssdev->ctrl.pixel_size;
341 break;
342 case OMAP_DISPLAY_TYPE_DSI:
343 bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
344 break;
345 default:
346 BUG();
347 return false;
348 }
349
350 return bpp > 16;
351}
352
353void dss_init_device(struct platform_device *pdev, 319void dss_init_device(struct platform_device *pdev,
354 struct omap_dss_device *dssdev) 320 struct omap_dss_device *dssdev)
355{ 321{
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index a81b6d6deb57..3266be23fc0d 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -38,6 +38,8 @@
38static struct { 38static struct {
39 struct regulator *vdds_dsi_reg; 39 struct regulator *vdds_dsi_reg;
40 struct platform_device *dsidev; 40 struct platform_device *dsidev;
41
42 struct dss_lcd_mgr_config mgr_config;
41} dpi; 43} dpi;
42 44
43static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) 45static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
@@ -83,11 +85,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
83 85
84 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 86 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
85 87
86 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); 88 dpi.mgr_config.clock_info = dispc_cinfo;
87 if (r) {
88 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
89 return r;
90 }
91 89
92 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 90 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
93 *lck_div = dispc_cinfo.lck_div; 91 *lck_div = dispc_cinfo.lck_div;
@@ -112,9 +110,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
112 if (r) 110 if (r)
113 return r; 111 return r;
114 112
115 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); 113 dpi.mgr_config.clock_info = dispc_cinfo;
116 if (r)
117 return r;
118 114
119 *fck = dss_cinfo.fck; 115 *fck = dss_cinfo.fck;
120 *lck_div = dispc_cinfo.lck_div; 116 *lck_div = dispc_cinfo.lck_div;
@@ -155,15 +151,18 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
155 return 0; 151 return 0;
156} 152}
157 153
158static void dpi_basic_init(struct omap_dss_device *dssdev) 154static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
159{ 155{
160 dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); 156 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
161 dispc_mgr_enable_stallmode(dssdev->manager->id, false); 157
158 dpi.mgr_config.stallmode = false;
159 dpi.mgr_config.fifohandcheck = false;
160
161 dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines;
162 162
163 dispc_mgr_set_lcd_type_tft(dssdev->manager->id); 163 dpi.mgr_config.lcden_sig_polarity = 0;
164 164
165 dispc_mgr_set_tft_data_lines(dssdev->manager->id, 165 dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config);
166 dssdev->phy.dpi.data_lines);
167} 166}
168 167
169int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 168int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -196,8 +195,6 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
196 if (r) 195 if (r)
197 goto err_get_dispc; 196 goto err_get_dispc;
198 197
199 dpi_basic_init(dssdev);
200
201 if (dpi_use_dsi_pll(dssdev)) { 198 if (dpi_use_dsi_pll(dssdev)) {
202 r = dsi_runtime_get(dpi.dsidev); 199 r = dsi_runtime_get(dpi.dsidev);
203 if (r) 200 if (r)
@@ -212,6 +209,8 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
212 if (r) 209 if (r)
213 goto err_set_mode; 210 goto err_set_mode;
214 211
212 dpi_config_lcd_manager(dssdev);
213
215 mdelay(2); 214 mdelay(2);
216 215
217 r = dss_mgr_enable(dssdev->manager); 216 r = dss_mgr_enable(dssdev->manager);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index e0d43b275e3e..b07e8864f82f 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -331,6 +331,8 @@ struct dsi_data {
331 unsigned num_lanes_used; 331 unsigned num_lanes_used;
332 332
333 unsigned scp_clk_refcount; 333 unsigned scp_clk_refcount;
334
335 struct dss_lcd_mgr_config mgr_config;
334}; 336};
335 337
336struct dsi_packet_sent_handler_data { 338struct dsi_packet_sent_handler_data {
@@ -4337,14 +4339,40 @@ EXPORT_SYMBOL(omap_dsi_update);
4337 4339
4338/* Display funcs */ 4340/* Display funcs */
4339 4341
4340static int dsi_display_init_dispc(struct omap_dss_device *dssdev) 4342static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
4341{ 4343{
4344 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4345 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4346 struct dispc_clock_info dispc_cinfo;
4342 int r; 4347 int r;
4348 unsigned long long fck;
4349
4350 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
4351
4352 dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div;
4353 dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div;
4354
4355 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
4356 if (r) {
4357 DSSERR("Failed to calc dispc clocks\n");
4358 return r;
4359 }
4360
4361 dsi->mgr_config.clock_info = dispc_cinfo;
4362
4363 return 0;
4364}
4365
4366static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4367{
4368 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4369 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4343 struct omap_video_timings timings; 4370 struct omap_video_timings timings;
4371 int r;
4372 u32 irq = 0;
4344 4373
4345 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4374 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
4346 u16 dw, dh; 4375 u16 dw, dh;
4347 u32 irq;
4348 4376
4349 dssdev->driver->get_resolution(dssdev, &dw, &dh); 4377 dssdev->driver->get_resolution(dssdev, &dw, &dh);
4350 4378
@@ -4363,16 +4391,16 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4363 (void *) dssdev, irq); 4391 (void *) dssdev, irq);
4364 if (r) { 4392 if (r) {
4365 DSSERR("can't get FRAMEDONE irq\n"); 4393 DSSERR("can't get FRAMEDONE irq\n");
4366 return r; 4394 goto err;
4367 } 4395 }
4368 4396
4369 dispc_mgr_enable_stallmode(dssdev->manager->id, true); 4397 dsi->mgr_config.stallmode = true;
4370 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); 4398 dsi->mgr_config.fifohandcheck = true;
4371 } else { 4399 } else {
4372 timings = dssdev->panel.timings; 4400 timings = dssdev->panel.timings;
4373 4401
4374 dispc_mgr_enable_stallmode(dssdev->manager->id, false); 4402 dsi->mgr_config.stallmode = false;
4375 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); 4403 dsi->mgr_config.fifohandcheck = false;
4376 } 4404 }
4377 4405
4378 /* 4406 /*
@@ -4388,12 +4416,24 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4388 4416
4389 dss_mgr_set_timings(dssdev->manager, &timings); 4417 dss_mgr_set_timings(dssdev->manager, &timings);
4390 4418
4391 dispc_mgr_set_lcd_type_tft(dssdev->manager->id); 4419 r = dsi_configure_dispc_clocks(dssdev);
4420 if (r)
4421 goto err1;
4422
4423 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
4424 dsi->mgr_config.video_port_width =
4425 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
4426 dsi->mgr_config.lcden_sig_polarity = 0;
4392 4427
4393 dispc_mgr_set_tft_data_lines(dssdev->manager->id, 4428 dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config);
4394 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt));
4395 4429
4396 return 0; 4430 return 0;
4431err1:
4432 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE)
4433 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4434 (void *) dssdev, irq);
4435err:
4436 return r;
4397} 4437}
4398 4438
4399static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4439static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
@@ -4433,33 +4473,6 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
4433 return 0; 4473 return 0;
4434} 4474}
4435 4475
4436static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
4437{
4438 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4439 struct dispc_clock_info dispc_cinfo;
4440 int r;
4441 unsigned long long fck;
4442
4443 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
4444
4445 dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div;
4446 dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div;
4447
4448 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
4449 if (r) {
4450 DSSERR("Failed to calc dispc clocks\n");
4451 return r;
4452 }
4453
4454 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
4455 if (r) {
4456 DSSERR("Failed to set dispc clocks\n");
4457 return r;
4458 }
4459
4460 return 0;
4461}
4462
4463static int dsi_display_init_dsi(struct omap_dss_device *dssdev) 4476static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4464{ 4477{
4465 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4478 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4481,10 +4494,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4481 4494
4482 DSSDBG("PLL OK\n"); 4495 DSSDBG("PLL OK\n");
4483 4496
4484 r = dsi_configure_dispc_clocks(dssdev);
4485 if (r)
4486 goto err2;
4487
4488 r = dsi_cio_init(dssdev); 4497 r = dsi_cio_init(dssdev);
4489 if (r) 4498 if (r)
4490 goto err2; 4499 goto err2;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6c5ecf02759e..f67afe76f217 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -158,6 +158,19 @@ struct reg_field {
158 u8 low; 158 u8 low;
159}; 159};
160 160
161struct dss_lcd_mgr_config {
162 enum dss_io_pad_mode io_pad_mode;
163
164 bool stallmode;
165 bool fifohandcheck;
166
167 struct dispc_clock_info clock_info;
168
169 int video_port_width;
170
171 int lcden_sig_polarity;
172};
173
161struct seq_file; 174struct seq_file;
162struct platform_device; 175struct platform_device;
163 176
@@ -194,6 +207,8 @@ int dss_mgr_set_device(struct omap_overlay_manager *mgr,
194int dss_mgr_unset_device(struct omap_overlay_manager *mgr); 207int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
195void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 208void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
196 struct omap_video_timings *timings); 209 struct omap_video_timings *timings);
210void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
211 const struct dss_lcd_mgr_config *config);
197const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); 212const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
198 213
199bool dss_ovl_is_enabled(struct omap_overlay *ovl); 214bool dss_ovl_is_enabled(struct omap_overlay *ovl);
@@ -216,8 +231,6 @@ void dss_init_device(struct platform_device *pdev,
216 struct omap_dss_device *dssdev); 231 struct omap_dss_device *dssdev);
217void dss_uninit_device(struct platform_device *pdev, 232void dss_uninit_device(struct platform_device *pdev,
218 struct omap_dss_device *dssdev); 233 struct omap_dss_device *dssdev);
219bool dss_use_replication(struct omap_dss_device *dssdev,
220 enum omap_color_mode mode);
221 234
222/* manager */ 235/* manager */
223int dss_init_overlay_managers(struct platform_device *pdev); 236int dss_init_overlay_managers(struct platform_device *pdev);
@@ -229,8 +242,18 @@ int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
229int dss_mgr_check(struct omap_overlay_manager *mgr, 242int dss_mgr_check(struct omap_overlay_manager *mgr,
230 struct omap_overlay_manager_info *info, 243 struct omap_overlay_manager_info *info,
231 const struct omap_video_timings *mgr_timings, 244 const struct omap_video_timings *mgr_timings,
245 const struct dss_lcd_mgr_config *config,
232 struct omap_overlay_info **overlay_infos); 246 struct omap_overlay_info **overlay_infos);
233 247
248static inline bool dss_mgr_is_lcd(enum omap_channel id)
249{
250 if (id == OMAP_DSS_CHANNEL_LCD || id == OMAP_DSS_CHANNEL_LCD2 ||
251 id == OMAP_DSS_CHANNEL_LCD3)
252 return true;
253 else
254 return false;
255}
256
234/* overlay */ 257/* overlay */
235void dss_init_overlays(struct platform_device *pdev); 258void dss_init_overlays(struct platform_device *pdev);
236void dss_uninit_overlays(struct platform_device *pdev); 259void dss_uninit_overlays(struct platform_device *pdev);
@@ -240,6 +263,8 @@ int dss_ovl_simple_check(struct omap_overlay *ovl,
240 const struct omap_overlay_info *info); 263 const struct omap_overlay_info *info);
241int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 264int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
242 const struct omap_video_timings *mgr_timings); 265 const struct omap_video_timings *mgr_timings);
266bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
267 enum omap_color_mode mode);
243 268
244/* DSS */ 269/* DSS */
245int dss_init_platform_driver(void) __init; 270int dss_init_platform_driver(void) __init;
@@ -425,7 +450,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
425unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); 450unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
426unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); 451unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
427unsigned long dispc_core_clk_rate(void); 452unsigned long dispc_core_clk_rate(void);
428int dispc_mgr_set_clock_div(enum omap_channel channel, 453void dispc_mgr_set_clock_div(enum omap_channel channel,
429 struct dispc_clock_info *cinfo); 454 struct dispc_clock_info *cinfo);
430int dispc_mgr_get_clock_div(enum omap_channel channel, 455int dispc_mgr_get_clock_div(enum omap_channel channel,
431 struct dispc_clock_info *cinfo); 456 struct dispc_clock_info *cinfo);
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index a51eb060c142..53710fadc82d 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -665,9 +665,40 @@ int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
665 return 0; 665 return 0;
666} 666}
667 667
668static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr,
669 const struct dss_lcd_mgr_config *config)
670{
671 struct dispc_clock_info cinfo = config->clock_info;
672 int dl = config->video_port_width;
673 bool stallmode = config->stallmode;
674 bool fifohandcheck = config->fifohandcheck;
675
676 if (cinfo.lck_div < 1 || cinfo.lck_div > 255)
677 return -EINVAL;
678
679 if (cinfo.pck_div < 1 || cinfo.pck_div > 255)
680 return -EINVAL;
681
682 if (dl != 12 && dl != 16 && dl != 18 && dl != 24)
683 return -EINVAL;
684
685 /* fifohandcheck should be used only with stallmode */
686 if (stallmode == false && fifohandcheck == true)
687 return -EINVAL;
688
689 /*
690 * io pad mode can be only checked by using dssdev connected to the
691 * manager. Ignore checking these for now, add checks when manager
692 * is capable of holding information related to the connected interface
693 */
694
695 return 0;
696}
697
668int dss_mgr_check(struct omap_overlay_manager *mgr, 698int dss_mgr_check(struct omap_overlay_manager *mgr,
669 struct omap_overlay_manager_info *info, 699 struct omap_overlay_manager_info *info,
670 const struct omap_video_timings *mgr_timings, 700 const struct omap_video_timings *mgr_timings,
701 const struct dss_lcd_mgr_config *lcd_config,
671 struct omap_overlay_info **overlay_infos) 702 struct omap_overlay_info **overlay_infos)
672{ 703{
673 struct omap_overlay *ovl; 704 struct omap_overlay *ovl;
@@ -683,6 +714,10 @@ int dss_mgr_check(struct omap_overlay_manager *mgr,
683 if (r) 714 if (r)
684 return r; 715 return r;
685 716
717 r = dss_mgr_check_lcd_config(mgr, lcd_config);
718 if (r)
719 return r;
720
686 list_for_each_entry(ovl, &mgr->overlays, list) { 721 list_for_each_entry(ovl, &mgr->overlays, list) {
687 struct omap_overlay_info *oi; 722 struct omap_overlay_info *oi;
688 int r; 723 int r;
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index ec69325a118a..952c6fad9a81 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -687,3 +687,16 @@ int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
687 687
688 return 0; 688 return 0;
689} 689}
690
691/*
692 * Checks if replication logic should be used. Only use when overlay is in
693 * RGB12U or RGB16 mode, and video port width interface is 18bpp or 24bpp
694 */
695bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
696 enum omap_color_mode mode)
697{
698 if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
699 return false;
700
701 return config.video_port_width > 16;
702}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 539d709c6c0e..7c087424b634 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -300,10 +300,11 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
300} 300}
301EXPORT_SYMBOL(omap_rfbi_write_pixels); 301EXPORT_SYMBOL(omap_rfbi_write_pixels);
302 302
303static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, 303static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
304 u16 height, void (*callback)(void *data), void *data) 304 u16 height, void (*callback)(void *data), void *data)
305{ 305{
306 u32 l; 306 u32 l;
307 int r;
307 struct omap_video_timings timings = { 308 struct omap_video_timings timings = {
308 .hsw = 1, 309 .hsw = 1,
309 .hfp = 1, 310 .hfp = 1,
@@ -322,7 +323,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
322 323
323 dss_mgr_set_timings(dssdev->manager, &timings); 324 dss_mgr_set_timings(dssdev->manager, &timings);
324 325
325 dispc_mgr_enable(dssdev->manager->id, true); 326 r = dss_mgr_enable(dssdev->manager);
327 if (r)
328 return r;
326 329
327 rfbi.framedone_callback = callback; 330 rfbi.framedone_callback = callback;
328 rfbi.framedone_callback_data = data; 331 rfbi.framedone_callback_data = data;
@@ -335,6 +338,8 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
335 l = FLD_MOD(l, 1, 4, 4); /* ITE */ 338 l = FLD_MOD(l, 1, 4, 4); /* ITE */
336 339
337 rfbi_write_reg(RFBI_CONTROL, l); 340 rfbi_write_reg(RFBI_CONTROL, l);
341
342 return 0;
338} 343}
339 344
340static void framedone_callback(void *data, u32 mask) 345static void framedone_callback(void *data, u32 mask)
@@ -814,8 +819,11 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
814 u16 x, u16 y, u16 w, u16 h, 819 u16 x, u16 y, u16 w, u16 h,
815 void (*callback)(void *), void *data) 820 void (*callback)(void *), void *data)
816{ 821{
817 rfbi_transfer_area(dssdev, w, h, callback, data); 822 int r;
818 return 0; 823
824 r = rfbi_transfer_area(dssdev, w, h, callback, data);
825
826 return r;
819} 827}
820EXPORT_SYMBOL(omap_rfbi_update); 828EXPORT_SYMBOL(omap_rfbi_update);
821 829
@@ -859,6 +867,22 @@ static void rfbi_dump_regs(struct seq_file *s)
859#undef DUMPREG 867#undef DUMPREG
860} 868}
861 869
870static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
871{
872 struct dss_lcd_mgr_config mgr_config;
873
874 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
875
876 mgr_config.stallmode = true;
877 /* Do we need fifohandcheck for RFBI? */
878 mgr_config.fifohandcheck = false;
879
880 mgr_config.video_port_width = dssdev->ctrl.pixel_size;
881 mgr_config.lcden_sig_polarity = 0;
882
883 dss_mgr_set_lcd_config(dssdev->manager, &mgr_config);
884}
885
862int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 886int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
863{ 887{
864 int r; 888 int r;
@@ -885,12 +909,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
885 goto err1; 909 goto err1;
886 } 910 }
887 911
888 dispc_mgr_set_lcd_type_tft(dssdev->manager->id); 912 rfbi_config_lcd_manager(dssdev);
889
890 dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI);
891 dispc_mgr_enable_stallmode(dssdev->manager->id, true);
892
893 dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
894 913
895 rfbi_configure(dssdev->phy.rfbi.channel, 914 rfbi_configure(dssdev->phy.rfbi.channel,
896 dssdev->ctrl.pixel_size, 915 dssdev->ctrl.pixel_size,
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 0fcd4d7e202e..5d31699fbd3c 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -32,18 +32,21 @@
32static struct { 32static struct {
33 bool update_enabled; 33 bool update_enabled;
34 struct regulator *vdds_sdi_reg; 34 struct regulator *vdds_sdi_reg;
35} sdi;
36 35
37static void sdi_basic_init(struct omap_dss_device *dssdev) 36 struct dss_lcd_mgr_config mgr_config;
37} sdi;
38 38
39static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
39{ 40{
40 dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); 41 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
41 dispc_mgr_enable_stallmode(dssdev->manager->id, false); 42
43 sdi.mgr_config.stallmode = false;
44 sdi.mgr_config.fifohandcheck = false;
42 45
43 dispc_mgr_set_lcd_type_tft(dssdev->manager->id); 46 sdi.mgr_config.video_port_width = 24;
47 sdi.mgr_config.lcden_sig_polarity = 1;
44 48
45 dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24); 49 dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config);
46 dispc_lcd_enable_signal_polarity(1);
47} 50}
48 51
49int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) 52int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
@@ -51,8 +54,6 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
51 struct omap_video_timings *t = &dssdev->panel.timings; 54 struct omap_video_timings *t = &dssdev->panel.timings;
52 struct dss_clock_info dss_cinfo; 55 struct dss_clock_info dss_cinfo;
53 struct dispc_clock_info dispc_cinfo; 56 struct dispc_clock_info dispc_cinfo;
54 u16 lck_div, pck_div;
55 unsigned long fck;
56 unsigned long pck; 57 unsigned long pck;
57 int r; 58 int r;
58 59
@@ -75,8 +76,6 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
75 if (r) 76 if (r)
76 goto err_get_dispc; 77 goto err_get_dispc;
77 78
78 sdi_basic_init(dssdev);
79
80 /* 15.5.9.1.2 */ 79 /* 15.5.9.1.2 */
81 dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 80 dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
82 dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 81 dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
@@ -85,11 +84,9 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
85 if (r) 84 if (r)
86 goto err_calc_clock_div; 85 goto err_calc_clock_div;
87 86
88 fck = dss_cinfo.fck; 87 sdi.mgr_config.clock_info = dispc_cinfo;
89 lck_div = dispc_cinfo.lck_div;
90 pck_div = dispc_cinfo.pck_div;
91 88
92 pck = fck / lck_div / pck_div / 1000; 89 pck = dss_cinfo.fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000;
93 90
94 if (pck != t->pixel_clock) { 91 if (pck != t->pixel_clock) {
95 DSSWARN("Could not find exact pixel clock. Requested %d kHz, " 92 DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
@@ -106,9 +103,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
106 if (r) 103 if (r)
107 goto err_set_dss_clock_div; 104 goto err_set_dss_clock_div;
108 105
109 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); 106 sdi_config_lcd_manager(dssdev);
110 if (r)
111 goto err_set_dispc_clock_div;
112 107
113 dss_sdi_init(dssdev->phy.sdi.datapairs); 108 dss_sdi_init(dssdev->phy.sdi.datapairs);
114 r = dss_sdi_enable(); 109 r = dss_sdi_enable();
@@ -125,7 +120,6 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
125err_mgr_enable: 120err_mgr_enable:
126 dss_sdi_disable(); 121 dss_sdi_disable();
127err_sdi_enable: 122err_sdi_enable:
128err_set_dispc_clock_div:
129err_set_dss_clock_div: 123err_set_dss_clock_div:
130err_calc_clock_div: 124err_calc_clock_div:
131 dispc_runtime_put(); 125 dispc_runtime_put();