~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/video/omap2/dss/dss.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <linux/seq_file.h>
30
30
#include <linux/clk.h>
31
31
 
32
 
#include <plat/display.h>
 
32
#include <video/omapdss.h>
33
33
#include <plat/clock.h>
34
34
#include "dss.h"
35
35
#include "dss_features.h"
45
45
#define DSS_REVISION                    DSS_REG(0x0000)
46
46
#define DSS_SYSCONFIG                   DSS_REG(0x0010)
47
47
#define DSS_SYSSTATUS                   DSS_REG(0x0014)
48
 
#define DSS_IRQSTATUS                   DSS_REG(0x0018)
49
48
#define DSS_CONTROL                     DSS_REG(0x0040)
50
49
#define DSS_SDI_CONTROL                 DSS_REG(0x0044)
51
50
#define DSS_PLL_CONTROL                 DSS_REG(0x0048)
75
74
        struct dss_clock_info cache_dss_cinfo;
76
75
        struct dispc_clock_info cache_dispc_cinfo;
77
76
 
78
 
        enum dss_clk_source dsi_clk_source;
79
 
        enum dss_clk_source dispc_clk_source;
80
 
        enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
 
77
        enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
 
78
        enum omap_dss_clk_source dispc_clk_source;
 
79
        enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
81
80
 
82
81
        u32             ctx[DSS_SZ_REGS / sizeof(u32)];
83
82
} dss;
84
83
 
85
 
static const struct dss_clk_source_name dss_generic_clk_source_names[] = {
86
 
        { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI_PLL_HSDIV_DISPC" },
87
 
        { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI_PLL_HSDIV_DSI" },
88
 
        { DSS_CLK_SRC_FCK, "DSS_FCK" },
 
84
static const char * const dss_generic_clk_source_names[] = {
 
85
        [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]  = "DSI_PLL_HSDIV_DISPC",
 
86
        [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]    = "DSI_PLL_HSDIV_DSI",
 
87
        [OMAP_DSS_CLK_SRC_FCK]                  = "DSS_FCK",
89
88
};
90
89
 
91
90
static void dss_clk_enable_all_no_ctx(void);
230
229
        REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
231
230
}
232
231
 
233
 
const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src)
 
232
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
234
233
{
235
 
        return dss_generic_clk_source_names[clk_src].clksrc_name;
 
234
        return dss_generic_clk_source_names[clk_src];
236
235
}
237
236
 
238
237
void dss_dump_clocks(struct seq_file *s)
239
238
{
240
239
        unsigned long dpll4_ck_rate;
241
240
        unsigned long dpll4_m4_ck_rate;
 
241
        const char *fclk_name, *fclk_real_name;
 
242
        unsigned long fclk_rate;
242
243
 
243
244
        dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
244
245
 
245
 
        dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
246
 
        dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
247
 
 
248
246
        seq_printf(s, "- DSS -\n");
249
247
 
250
 
        seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
251
 
 
252
 
        if (cpu_is_omap3630() || cpu_is_omap44xx())
253
 
                seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
254
 
                        dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK),
255
 
                        dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK),
256
 
                        dpll4_ck_rate,
257
 
                        dpll4_ck_rate / dpll4_m4_ck_rate,
258
 
                        dss_clk_get_rate(DSS_CLK_FCK));
259
 
        else
260
 
                seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
261
 
                        dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK),
262
 
                        dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK),
263
 
                        dpll4_ck_rate,
264
 
                        dpll4_ck_rate / dpll4_m4_ck_rate,
265
 
                        dss_clk_get_rate(DSS_CLK_FCK));
 
248
        fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
 
249
        fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
 
250
        fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
 
251
 
 
252
        if (dss.dpll4_m4_ck) {
 
253
                dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
 
254
                dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
 
255
 
 
256
                seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
 
257
 
 
258
                if (cpu_is_omap3630() || cpu_is_omap44xx())
 
259
                        seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
 
260
                                        fclk_name, fclk_real_name,
 
261
                                        dpll4_ck_rate,
 
262
                                        dpll4_ck_rate / dpll4_m4_ck_rate,
 
263
                                        fclk_rate);
 
264
                else
 
265
                        seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
 
266
                                        fclk_name, fclk_real_name,
 
267
                                        dpll4_ck_rate,
 
268
                                        dpll4_ck_rate / dpll4_m4_ck_rate,
 
269
                                        fclk_rate);
 
270
        } else {
 
271
                seq_printf(s, "%s (%s) = %lu\n",
 
272
                                fclk_name, fclk_real_name,
 
273
                                fclk_rate);
 
274
        }
266
275
 
267
276
        dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
268
277
}
276
285
        DUMPREG(DSS_REVISION);
277
286
        DUMPREG(DSS_SYSCONFIG);
278
287
        DUMPREG(DSS_SYSSTATUS);
279
 
        DUMPREG(DSS_IRQSTATUS);
280
288
        DUMPREG(DSS_CONTROL);
281
289
 
282
290
        if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
290
298
#undef DUMPREG
291
299
}
292
300
 
293
 
void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
 
301
void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
294
302
{
 
303
        struct platform_device *dsidev;
295
304
        int b;
296
305
        u8 start, end;
297
306
 
298
307
        switch (clk_src) {
299
 
        case DSS_CLK_SRC_FCK:
 
308
        case OMAP_DSS_CLK_SRC_FCK:
300
309
                b = 0;
301
310
                break;
302
 
        case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 
311
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
303
312
                b = 1;
304
 
                dsi_wait_pll_hsdiv_dispc_active();
 
313
                dsidev = dsi_get_dsidev_from_id(0);
 
314
                dsi_wait_pll_hsdiv_dispc_active(dsidev);
 
315
                break;
 
316
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
 
317
                b = 2;
 
318
                dsidev = dsi_get_dsidev_from_id(1);
 
319
                dsi_wait_pll_hsdiv_dispc_active(dsidev);
305
320
                break;
306
321
        default:
307
322
                BUG();
314
329
        dss.dispc_clk_source = clk_src;
315
330
}
316
331
 
317
 
void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
 
332
void dss_select_dsi_clk_source(int dsi_module,
 
333
                enum omap_dss_clk_source clk_src)
318
334
{
 
335
        struct platform_device *dsidev;
319
336
        int b;
320
337
 
321
338
        switch (clk_src) {
322
 
        case DSS_CLK_SRC_FCK:
 
339
        case OMAP_DSS_CLK_SRC_FCK:
323
340
                b = 0;
324
341
                break;
325
 
        case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
326
 
                b = 1;
327
 
                dsi_wait_pll_hsdiv_dsi_active();
 
342
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
 
343
                BUG_ON(dsi_module != 0);
 
344
                b = 1;
 
345
                dsidev = dsi_get_dsidev_from_id(0);
 
346
                dsi_wait_pll_hsdiv_dsi_active(dsidev);
 
347
                break;
 
348
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
 
349
                BUG_ON(dsi_module != 1);
 
350
                b = 1;
 
351
                dsidev = dsi_get_dsidev_from_id(1);
 
352
                dsi_wait_pll_hsdiv_dsi_active(dsidev);
328
353
                break;
329
354
        default:
330
355
                BUG();
332
357
 
333
358
        REG_FLD_MOD(DSS_CONTROL, b, 1, 1);      /* DSI_CLK_SWITCH */
334
359
 
335
 
        dss.dsi_clk_source = clk_src;
 
360
        dss.dsi_clk_source[dsi_module] = clk_src;
336
361
}
337
362
 
338
363
void dss_select_lcd_clk_source(enum omap_channel channel,
339
 
                enum dss_clk_source clk_src)
 
364
                enum omap_dss_clk_source clk_src)
340
365
{
 
366
        struct platform_device *dsidev;
341
367
        int b, ix, pos;
342
368
 
343
369
        if (!dss_has_feature(FEAT_LCD_CLK_SRC))
344
370
                return;
345
371
 
346
372
        switch (clk_src) {
347
 
        case DSS_CLK_SRC_FCK:
 
373
        case OMAP_DSS_CLK_SRC_FCK:
348
374
                b = 0;
349
375
                break;
350
 
        case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 
376
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
351
377
                BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
352
378
                b = 1;
353
 
                dsi_wait_pll_hsdiv_dispc_active();
 
379
                dsidev = dsi_get_dsidev_from_id(0);
 
380
                dsi_wait_pll_hsdiv_dispc_active(dsidev);
 
381
                break;
 
382
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
 
383
                BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2);
 
384
                b = 1;
 
385
                dsidev = dsi_get_dsidev_from_id(1);
 
386
                dsi_wait_pll_hsdiv_dispc_active(dsidev);
354
387
                break;
355
388
        default:
356
389
                BUG();
363
396
        dss.lcd_clk_source[ix] = clk_src;
364
397
}
365
398
 
366
 
enum dss_clk_source dss_get_dispc_clk_source(void)
 
399
enum omap_dss_clk_source dss_get_dispc_clk_source(void)
367
400
{
368
401
        return dss.dispc_clk_source;
369
402
}
370
403
 
371
 
enum dss_clk_source dss_get_dsi_clk_source(void)
 
404
enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
372
405
{
373
 
        return dss.dsi_clk_source;
 
406
        return dss.dsi_clk_source[dsi_module];
374
407
}
375
408
 
376
 
enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
 
409
enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
377
410
{
378
 
        int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
379
 
        return dss.lcd_clk_source[ix];
 
411
        if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
 
412
                int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
 
413
                return dss.lcd_clk_source[ix];
 
414
        } else {
 
415
                /* LCD_CLK source is the same as DISPC_FCLK source for
 
416
                 * OMAP2 and OMAP3 */
 
417
                return dss.dispc_clk_source;
 
418
        }
380
419
}
381
420
 
382
421
/* calculate clock rates using dividers in cinfo */
383
422
int dss_calc_clock_rates(struct dss_clock_info *cinfo)
384
423
{
385
 
        unsigned long prate;
386
 
        u16 fck_div_max = 16;
387
 
 
388
 
        if (cpu_is_omap3630() || cpu_is_omap44xx())
389
 
                fck_div_max = 32;
390
 
 
391
 
        if ((cinfo->fck_div > fck_div_max) || cinfo->fck_div == 0)
392
 
                return -EINVAL;
393
 
 
394
 
        prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
395
 
 
396
 
        cinfo->fck = prate / cinfo->fck_div;
 
424
        if (dss.dpll4_m4_ck) {
 
425
                unsigned long prate;
 
426
                u16 fck_div_max = 16;
 
427
 
 
428
                if (cpu_is_omap3630() || cpu_is_omap44xx())
 
429
                        fck_div_max = 32;
 
430
 
 
431
                if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
 
432
                        return -EINVAL;
 
433
 
 
434
                prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
 
435
 
 
436
                cinfo->fck = prate / cinfo->fck_div;
 
437
        } else {
 
438
                if (cinfo->fck_div != 0)
 
439
                        return -EINVAL;
 
440
                cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
 
441
        }
397
442
 
398
443
        return 0;
399
444
}
400
445
 
401
446
int dss_set_clock_div(struct dss_clock_info *cinfo)
402
447
{
403
 
        unsigned long prate;
404
 
        int r;
 
448
        if (dss.dpll4_m4_ck) {
 
449
                unsigned long prate;
 
450
                int r;
405
451
 
406
 
        if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
407
452
                prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
408
453
                DSSDBG("dpll4_m4 = %ld\n", prate);
409
454
 
410
455
                r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
411
456
                if (r)
412
457
                        return r;
 
458
        } else {
 
459
                if (cinfo->fck_div != 0)
 
460
                        return -EINVAL;
413
461
        }
414
462
 
415
463
        DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
421
469
{
422
470
        cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
423
471
 
424
 
        if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
 
472
        if (dss.dpll4_m4_ck) {
425
473
                unsigned long prate;
 
474
 
426
475
                prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
 
476
 
427
477
                if (cpu_is_omap3630() || cpu_is_omap44xx())
428
478
                        cinfo->fck_div = prate / (cinfo->fck);
429
479
                else
437
487
 
438
488
unsigned long dss_get_dpll4_rate(void)
439
489
{
440
 
        if (cpu_is_omap34xx() || cpu_is_omap44xx())
 
490
        if (dss.dpll4_m4_ck)
441
491
                return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
442
492
        else
443
493
                return 0;
460
510
 
461
511
        prate = dss_get_dpll4_rate();
462
512
 
463
 
        max_dss_fck = dss_feat_get_max_dss_fck();
 
513
        max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
464
514
 
465
515
        fck = dss_clk_get_rate(DSS_CLK_FCK);
466
516
        if (req_pck == dss.cache_req_pck &&
486
536
        memset(&best_dss, 0, sizeof(best_dss));
487
537
        memset(&best_dispc, 0, sizeof(best_dispc));
488
538
 
489
 
        if (cpu_is_omap24xx()) {
 
539
        if (dss.dpll4_m4_ck == NULL) {
490
540
                struct dispc_clock_info cur_dispc;
491
541
                /* XXX can we change the clock on omap2? */
492
542
                fck = dss_clk_get_rate(DSS_CLK_FCK);
501
551
                best_dispc = cur_dispc;
502
552
 
503
553
                goto found;
504
 
        } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
505
 
 
 
554
        } else {
506
555
                if (cpu_is_omap3630() || cpu_is_omap44xx())
507
556
                        fck_div_max = 32;
508
557
 
537
586
                                        goto found;
538
587
                        }
539
588
                }
540
 
        } else {
541
 
                BUG();
542
589
        }
543
590
 
544
591
found:
621
668
        int r;
622
669
        u32 rev;
623
670
        struct resource *dss_mem;
 
671
        struct clk *dpll4_m4_ck;
624
672
 
625
673
        dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
626
674
        if (!dss_mem) {
640
688
         * the kernel resets it */
641
689
        omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
642
690
 
 
691
#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
643
692
        /* We need to wait here a bit, otherwise we sometimes start to
644
693
         * get synclost errors, and after that only power cycle will
645
694
         * restore DSS functionality. I have no idea why this happens.
646
695
         * And we have to wait _before_ resetting the DSS, but after
647
696
         * enabling clocks.
 
697
         *
 
698
         * This bug was at least present on OMAP3430. It's unknown
 
699
         * if it happens on OMAP2 or OMAP3630.
648
700
         */
649
701
        msleep(50);
 
702
#endif
650
703
 
651
704
        _omap_dss_reset();
652
705
 
661
714
        REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
662
715
        REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
663
716
#endif
664
 
 
665
717
        if (cpu_is_omap34xx()) {
666
 
                dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
667
 
                if (IS_ERR(dss.dpll4_m4_ck)) {
 
718
                dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
 
719
                if (IS_ERR(dpll4_m4_ck)) {
668
720
                        DSSERR("Failed to get dpll4_m4_ck\n");
669
 
                        r = PTR_ERR(dss.dpll4_m4_ck);
 
721
                        r = PTR_ERR(dpll4_m4_ck);
670
722
                        goto fail1;
671
723
                }
672
724
        } else if (cpu_is_omap44xx()) {
673
 
                dss.dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
674
 
                if (IS_ERR(dss.dpll4_m4_ck)) {
 
725
                dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
 
726
                if (IS_ERR(dpll4_m4_ck)) {
675
727
                        DSSERR("Failed to get dpll4_m4_ck\n");
676
 
                        r = PTR_ERR(dss.dpll4_m4_ck);
 
728
                        r = PTR_ERR(dpll4_m4_ck);
677
729
                        goto fail1;
678
730
                }
 
731
        } else { /* omap24xx */
 
732
                dpll4_m4_ck = NULL;
679
733
        }
680
734
 
681
 
        dss.dsi_clk_source = DSS_CLK_SRC_FCK;
682
 
        dss.dispc_clk_source = DSS_CLK_SRC_FCK;
683
 
        dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
684
 
        dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
 
735
        dss.dpll4_m4_ck = dpll4_m4_ck;
 
736
 
 
737
        dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
 
738
        dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 
739
        dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
 
740
        dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
 
741
        dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
685
742
 
686
743
        dss_save_context();
687
744
 
699
756
 
700
757
static void dss_exit(void)
701
758
{
702
 
        if (cpu_is_omap34xx() || cpu_is_omap44xx())
 
759
        if (dss.dpll4_m4_ck)
703
760
                clk_put(dss.dpll4_m4_ck);
704
761
 
705
762
        iounmap(dss.base);
993
1050
                dss.dss_video_fck
994
1051
        };
995
1052
 
 
1053
        const char *names[5] = {
 
1054
                "ick",
 
1055
                "fck",
 
1056
                "sys_clk",
 
1057
                "tv_fck",
 
1058
                "video_fck"
 
1059
        };
 
1060
 
996
1061
        seq_printf(s, "- CORE -\n");
997
1062
 
998
1063
        seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
1000
1065
        for (i = 0; i < 5; i++) {
1001
1066
                if (!clocks[i])
1002
1067
                        continue;
1003
 
                seq_printf(s, "%-15s\t%lu\t%d\n",
 
1068
                seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
 
1069
                                names[i],
1004
1070
                                clocks[i]->name,
 
1071
                                24 - strlen(names[i]) - strlen(clocks[i]->name),
 
1072
                                "",
1005
1073
                                clk_get_rate(clocks[i]),
1006
1074
                                clocks[i]->usecount);
1007
1075
        }