aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/dss
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2016-05-17 08:46:19 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2016-05-19 13:19:05 -0400
commitc63b1ec0904a074ae311103109b3e9946e38f2fa (patch)
tree1c18b76d9122e1ed855a79f11c5bf7c35678e43f /drivers/gpu/drm/omapdrm/dss
parent06ede3dd96e16b41618b656b54467b9eb924870f (diff)
drm/omap: clean up the LCD clk mux code
The code to set the clock muxes for DISPC's LCD clock inputs is very confusing. Especially on DRA7, there's an additional clock muxing that needs to be done, which at the moment is done in dpi.c using dss_ctrl_pll_set_control_mux(). Clean this all up by: - Using dss_clk_source instead of dss_pll_id, as dss_pll_id doesn't specify the clock source quite correctly. - Splitting the dss_select_lcd_clk_source() up into DSS version specific helper functions. - Using dss_ctrl_pll_set_control_mux() from the helper functions, so that dpi.c doesn't have to call it. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c4
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c186
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.h2
3 files changed, 141 insertions, 51 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 487d0549bd23..d4fbc46536d9 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -606,10 +606,6 @@ static void dpi_init_pll(struct dpi_data *dpi)
606 if (!pll) 606 if (!pll)
607 return; 607 return;
608 608
609 /* On DRA7 we need to set a mux to use the PLL */
610 if (omapdss_get_version() == OMAPDSS_VER_DRA7xx)
611 dss_ctrl_pll_set_control_mux(pll->id, dpi->output.dispc_channel);
612
613 if (dpi_verify_dsi_pll(pll)) { 609 if (dpi_verify_dsi_pll(pll)) {
614 DSSWARN("DSI PLL not operational\n"); 610 DSSWARN("DSI PLL not operational\n");
615 return; 611 return;
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 598a51b44e4a..2937a2812690 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -75,6 +75,8 @@ struct dss_features {
75 const enum omap_display_type *ports; 75 const enum omap_display_type *ports;
76 int num_ports; 76 int num_ports;
77 int (*dpi_select_source)(int port, enum omap_channel channel); 77 int (*dpi_select_source)(int port, enum omap_channel channel);
78 int (*select_lcd_source)(enum omap_channel channel,
79 enum dss_clk_source clk_src);
78}; 80};
79 81
80static struct { 82static struct {
@@ -205,68 +207,70 @@ void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
205 1 << shift, val << shift); 207 1 << shift, val << shift);
206} 208}
207 209
208void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id, 210static int dss_ctrl_pll_set_control_mux(enum dss_clk_source clk_src,
209 enum omap_channel channel) 211 enum omap_channel channel)
210{ 212{
211 unsigned shift, val; 213 unsigned shift, val;
212 214
213 if (!dss.syscon_pll_ctrl) 215 if (!dss.syscon_pll_ctrl)
214 return; 216 return -EINVAL;
215 217
216 switch (channel) { 218 switch (channel) {
217 case OMAP_DSS_CHANNEL_LCD: 219 case OMAP_DSS_CHANNEL_LCD:
218 shift = 3; 220 shift = 3;
219 221
220 switch (pll_id) { 222 switch (clk_src) {
221 case DSS_PLL_VIDEO1: 223 case DSS_CLK_SRC_PLL1_1:
222 val = 0; break; 224 val = 0; break;
223 case DSS_PLL_HDMI: 225 case DSS_CLK_SRC_HDMI_PLL:
224 val = 1; break; 226 val = 1; break;
225 default: 227 default:
226 DSSERR("error in PLL mux config for LCD\n"); 228 DSSERR("error in PLL mux config for LCD\n");
227 return; 229 return -EINVAL;
228 } 230 }
229 231
230 break; 232 break;
231 case OMAP_DSS_CHANNEL_LCD2: 233 case OMAP_DSS_CHANNEL_LCD2:
232 shift = 5; 234 shift = 5;
233 235
234 switch (pll_id) { 236 switch (clk_src) {
235 case DSS_PLL_VIDEO1: 237 case DSS_CLK_SRC_PLL1_3:
236 val = 0; break; 238 val = 0; break;
237 case DSS_PLL_VIDEO2: 239 case DSS_CLK_SRC_PLL2_3:
238 val = 1; break; 240 val = 1; break;
239 case DSS_PLL_HDMI: 241 case DSS_CLK_SRC_HDMI_PLL:
240 val = 2; break; 242 val = 2; break;
241 default: 243 default:
242 DSSERR("error in PLL mux config for LCD2\n"); 244 DSSERR("error in PLL mux config for LCD2\n");
243 return; 245 return -EINVAL;
244 } 246 }
245 247
246 break; 248 break;
247 case OMAP_DSS_CHANNEL_LCD3: 249 case OMAP_DSS_CHANNEL_LCD3:
248 shift = 7; 250 shift = 7;
249 251
250 switch (pll_id) { 252 switch (clk_src) {
251 case DSS_PLL_VIDEO1: 253 case DSS_CLK_SRC_PLL2_1:
252 val = 1; break;
253 case DSS_PLL_VIDEO2:
254 val = 0; break; 254 val = 0; break;
255 case DSS_PLL_HDMI: 255 case DSS_CLK_SRC_PLL1_3:
256 val = 1; break;
257 case DSS_CLK_SRC_HDMI_PLL:
256 val = 2; break; 258 val = 2; break;
257 default: 259 default:
258 DSSERR("error in PLL mux config for LCD3\n"); 260 DSSERR("error in PLL mux config for LCD3\n");
259 return; 261 return -EINVAL;
260 } 262 }
261 263
262 break; 264 break;
263 default: 265 default:
264 DSSERR("error in PLL mux config\n"); 266 DSSERR("error in PLL mux config\n");
265 return; 267 return -EINVAL;
266 } 268 }
267 269
268 regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset, 270 regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
269 0x3 << shift, val << shift); 271 0x3 << shift, val << shift);
272
273 return 0;
270} 274}
271 275
272void dss_sdi_init(int datapairs) 276void dss_sdi_init(int datapairs)
@@ -404,11 +408,34 @@ static void dss_dump_regs(struct seq_file *s)
404#undef DUMPREG 408#undef DUMPREG
405} 409}
406 410
411static int dss_get_channel_index(enum omap_channel channel)
412{
413 switch (channel) {
414 case OMAP_DSS_CHANNEL_LCD:
415 return 0;
416 case OMAP_DSS_CHANNEL_LCD2:
417 return 1;
418 case OMAP_DSS_CHANNEL_LCD3:
419 return 2;
420 default:
421 WARN_ON(1);
422 return 0;
423 }
424}
425
407static void dss_select_dispc_clk_source(enum dss_clk_source clk_src) 426static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
408{ 427{
409 int b; 428 int b;
410 u8 start, end; 429 u8 start, end;
411 430
431 /*
432 * We always use PRCM clock as the DISPC func clock, except on DSS3,
433 * where we don't have separate DISPC and LCD clock sources.
434 */
435 if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) &&
436 clk_src != DSS_CLK_SRC_FCK))
437 return;
438
412 switch (clk_src) { 439 switch (clk_src) {
413 case DSS_CLK_SRC_FCK: 440 case DSS_CLK_SRC_FCK:
414 b = 0; 441 b = 0;
@@ -459,41 +486,108 @@ void dss_select_dsi_clk_source(int dsi_module,
459 dss.dsi_clk_source[dsi_module] = clk_src; 486 dss.dsi_clk_source[dsi_module] = clk_src;
460} 487}
461 488
489static int dss_lcd_clk_mux_dra7(enum omap_channel channel,
490 enum dss_clk_source clk_src)
491{
492 const u8 ctrl_bits[] = {
493 [OMAP_DSS_CHANNEL_LCD] = 0,
494 [OMAP_DSS_CHANNEL_LCD2] = 12,
495 [OMAP_DSS_CHANNEL_LCD3] = 19,
496 };
497
498 u8 ctrl_bit = ctrl_bits[channel];
499 int r;
500
501 if (clk_src == DSS_CLK_SRC_FCK) {
502 /* LCDx_CLK_SWITCH */
503 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
504 return -EINVAL;
505 }
506
507 r = dss_ctrl_pll_set_control_mux(clk_src, channel);
508 if (r)
509 return r;
510
511 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
512
513 return 0;
514}
515
516static int dss_lcd_clk_mux_omap5(enum omap_channel channel,
517 enum dss_clk_source clk_src)
518{
519 const u8 ctrl_bits[] = {
520 [OMAP_DSS_CHANNEL_LCD] = 0,
521 [OMAP_DSS_CHANNEL_LCD2] = 12,
522 [OMAP_DSS_CHANNEL_LCD3] = 19,
523 };
524 const enum dss_clk_source allowed_plls[] = {
525 [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
526 [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_FCK,
527 [OMAP_DSS_CHANNEL_LCD3] = DSS_CLK_SRC_PLL2_1,
528 };
529
530 u8 ctrl_bit = ctrl_bits[channel];
531
532 if (clk_src == DSS_CLK_SRC_FCK) {
533 /* LCDx_CLK_SWITCH */
534 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
535 return -EINVAL;
536 }
537
538 if (WARN_ON(allowed_plls[channel] != clk_src))
539 return -EINVAL;
540
541 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
542
543 return 0;
544}
545
546static int dss_lcd_clk_mux_omap4(enum omap_channel channel,
547 enum dss_clk_source clk_src)
548{
549 const u8 ctrl_bits[] = {
550 [OMAP_DSS_CHANNEL_LCD] = 0,
551 [OMAP_DSS_CHANNEL_LCD2] = 12,
552 };
553 const enum dss_clk_source allowed_plls[] = {
554 [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
555 [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_PLL2_1,
556 };
557
558 u8 ctrl_bit = ctrl_bits[channel];
559
560 if (clk_src == DSS_CLK_SRC_FCK) {
561 /* LCDx_CLK_SWITCH */
562 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
563 return 0;
564 }
565
566 if (WARN_ON(allowed_plls[channel] != clk_src))
567 return -EINVAL;
568
569 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
570
571 return 0;
572}
573
462void dss_select_lcd_clk_source(enum omap_channel channel, 574void dss_select_lcd_clk_source(enum omap_channel channel,
463 enum dss_clk_source clk_src) 575 enum dss_clk_source clk_src)
464{ 576{
465 int b, ix, pos; 577 int idx = dss_get_channel_index(channel);
578 int r;
466 579
467 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { 580 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
468 dss_select_dispc_clk_source(clk_src); 581 dss_select_dispc_clk_source(clk_src);
582 dss.lcd_clk_source[idx] = clk_src;
469 return; 583 return;
470 } 584 }
471 585
472 switch (clk_src) { 586 r = dss.feat->select_lcd_source(channel, clk_src);
473 case DSS_CLK_SRC_FCK: 587 if (r)
474 b = 0;
475 break;
476 case DSS_CLK_SRC_PLL1_1:
477 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
478 b = 1;
479 break;
480 case DSS_CLK_SRC_PLL2_1:
481 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
482 channel != OMAP_DSS_CHANNEL_LCD3);
483 b = 1;
484 break;
485 default:
486 BUG();
487 return; 588 return;
488 }
489
490 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
491 (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
492 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
493 589
494 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 590 dss.lcd_clk_source[idx] = clk_src;
495 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
496 dss.lcd_clk_source[ix] = clk_src;
497} 591}
498 592
499enum dss_clk_source dss_get_dispc_clk_source(void) 593enum dss_clk_source dss_get_dispc_clk_source(void)
@@ -509,9 +603,8 @@ enum dss_clk_source dss_get_dsi_clk_source(int dsi_module)
509enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) 603enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
510{ 604{
511 if (dss_has_feature(FEAT_LCD_CLK_SRC)) { 605 if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
512 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 606 int idx = dss_get_channel_index(channel);
513 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2); 607 return dss.lcd_clk_source[idx];
514 return dss.lcd_clk_source[ix];
515 } else { 608 } else {
516 /* LCD_CLK source is the same as DISPC_FCLK source for 609 /* LCD_CLK source is the same as DISPC_FCLK source for
517 * OMAP2 and OMAP3 */ 610 * OMAP2 and OMAP3 */
@@ -860,6 +953,7 @@ static const struct dss_features omap44xx_dss_feats = {
860 .dpi_select_source = &dss_dpi_select_source_omap4, 953 .dpi_select_source = &dss_dpi_select_source_omap4,
861 .ports = omap2plus_ports, 954 .ports = omap2plus_ports,
862 .num_ports = ARRAY_SIZE(omap2plus_ports), 955 .num_ports = ARRAY_SIZE(omap2plus_ports),
956 .select_lcd_source = &dss_lcd_clk_mux_omap4,
863}; 957};
864 958
865static const struct dss_features omap54xx_dss_feats = { 959static const struct dss_features omap54xx_dss_feats = {
@@ -869,6 +963,7 @@ static const struct dss_features omap54xx_dss_feats = {
869 .dpi_select_source = &dss_dpi_select_source_omap5, 963 .dpi_select_source = &dss_dpi_select_source_omap5,
870 .ports = omap2plus_ports, 964 .ports = omap2plus_ports,
871 .num_ports = ARRAY_SIZE(omap2plus_ports), 965 .num_ports = ARRAY_SIZE(omap2plus_ports),
966 .select_lcd_source = &dss_lcd_clk_mux_omap5,
872}; 967};
873 968
874static const struct dss_features am43xx_dss_feats = { 969static const struct dss_features am43xx_dss_feats = {
@@ -887,6 +982,7 @@ static const struct dss_features dra7xx_dss_feats = {
887 .dpi_select_source = &dss_dpi_select_source_dra7xx, 982 .dpi_select_source = &dss_dpi_select_source_dra7xx,
888 .ports = dra7xx_ports, 983 .ports = dra7xx_ports,
889 .num_ports = ARRAY_SIZE(dra7xx_ports), 984 .num_ports = ARRAY_SIZE(dra7xx_ports),
985 .select_lcd_source = &dss_lcd_clk_mux_dra7,
890}; 986};
891 987
892static int dss_init_features(struct platform_device *pdev) 988static int dss_init_features(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h
index 52895ba2d717..1ef53bbdddea 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss.h
@@ -265,8 +265,6 @@ void dss_debug_dump_clocks(struct seq_file *s);
265#endif 265#endif
266 266
267void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable); 267void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable);
268void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
269 enum omap_channel channel);
270 268
271void dss_sdi_init(int datapairs); 269void dss_sdi_init(int datapairs);
272int dss_sdi_enable(void); 270int dss_sdi_enable(void);