74
73
#define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400)
75
74
#define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404)
76
75
#define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408)
77
#define DISPC_DIVISOR(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
76
#define DISPC_DIVISORo(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
78
77
#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
79
78
#define DISPC_SIZE_DIG DISPC_REG(0x0078)
80
79
#define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC)
552
560
static inline void enable_clocks(bool enable)
555
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
563
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
557
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
565
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
560
568
bool dispc_go_busy(enum omap_channel channel)
1000
1008
enable_clocks(0);
1011
void dispc_enable_gamma_table(bool enable)
1014
* This is partially implemented to support only disabling of
1018
DSSWARN("Gamma table enabling for TV not yet supported");
1022
REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
1003
1025
static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
1130
1152
const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
1131
1153
DISPC_VID_ACCU0(1) };
1154
u8 hor_start, hor_end, vert_start, vert_end;
1133
1156
BUG_ON(plane == OMAP_DSS_GFX);
1135
val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
1158
dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1159
dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1161
val = FLD_VAL(vaccu, vert_start, vert_end) |
1162
FLD_VAL(haccu, hor_start, hor_end);
1136
1164
dispc_write_reg(ac0_reg[plane-1], val);
1142
1170
const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
1143
1171
DISPC_VID_ACCU1(1) };
1172
u8 hor_start, hor_end, vert_start, vert_end;
1145
1174
BUG_ON(plane == OMAP_DSS_GFX);
1147
val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
1176
dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1177
dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1179
val = FLD_VAL(vaccu, vert_start, vert_end) |
1180
FLD_VAL(haccu, hor_start, hor_end);
1148
1182
dispc_write_reg(ac1_reg[plane-1], val);
1182
1216
_dispc_set_fir(plane, fir_hinc, fir_vinc);
1184
1218
l = dispc_read_reg(dispc_reg_att[plane]);
1185
l &= ~((0x0f << 5) | (0x3 << 21));
1220
/* RESIZEENABLE and VERTICALTAPS */
1221
l &= ~((0x3 << 5) | (0x1 << 21));
1187
1222
l |= fir_hinc ? (1 << 5) : 0;
1188
1223
l |= fir_vinc ? (1 << 6) : 0;
1190
l |= hscaleup ? 0 : (1 << 7);
1191
l |= vscaleup ? 0 : (1 << 8);
1193
1224
l |= five_taps ? (1 << 21) : 0;
1194
l |= five_taps ? (1 << 22) : 0;
1226
/* VRESIZECONF and HRESIZECONF */
1227
if (dss_has_feature(FEAT_RESIZECONF)) {
1229
l |= hscaleup ? 0 : (1 << 7);
1230
l |= vscaleup ? 0 : (1 << 8);
1233
/* LINEBUFFERSPLIT */
1234
if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
1236
l |= five_taps ? (1 << 22) : 0;
1196
1239
dispc_write_reg(dispc_reg_att[plane], l);
1254
REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
1256
1299
if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1257
REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
1259
REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
1261
REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
1262
REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
1305
REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
1306
if (dss_has_feature(FEAT_ROWREPEATENABLE))
1307
REG_FLD_MOD(dispc_reg_att[plane], row_repeat ? 1 : 0, 18, 18);
1266
1310
static int color_mode_to_bpp(enum omap_color_mode color_mode)
2312
2356
unsigned long r = 0;
2314
if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
2315
r = dss_clk_get_rate(DSS_CLK_FCK1);
2317
#ifdef CONFIG_OMAP2_DSS_DSI
2318
r = dsi_get_dsi1_pll_rate();
2358
switch (dss_get_dispc_clk_source()) {
2359
case DSS_CLK_SRC_FCK:
2360
r = dss_clk_get_rate(DSS_CLK_FCK);
2362
case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2363
r = dsi_get_pll_hsdiv_dispc_rate();
2328
2375
unsigned long r;
2331
l = dispc_read_reg(DISPC_DIVISOR(channel));
2378
l = dispc_read_reg(DISPC_DIVISORo(channel));
2333
2380
lcd = FLD_GET(l, 23, 16);
2335
r = dispc_fclk_rate();
2382
switch (dss_get_lcd_clk_source(channel)) {
2383
case DSS_CLK_SRC_FCK:
2384
r = dss_clk_get_rate(DSS_CLK_FCK);
2386
case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2387
r = dsi_get_pll_hsdiv_dispc_rate();
2337
2393
return r / lcd;
2340
2396
unsigned long dispc_pclk_rate(enum omap_channel channel)
2343
2399
unsigned long r;
2346
l = dispc_read_reg(DISPC_DIVISOR(channel));
2402
l = dispc_read_reg(DISPC_DIVISORo(channel));
2348
lcd = FLD_GET(l, 23, 16);
2349
2404
pcd = FLD_GET(l, 7, 0);
2351
r = dispc_fclk_rate();
2406
r = dispc_lclk_rate(channel);
2353
return r / lcd / pcd;
2356
2411
void dispc_dump_clocks(struct seq_file *s)
2415
enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
2416
enum dss_clk_source lcd_clk_src;
2360
2418
enable_clocks(1);
2362
2420
seq_printf(s, "- DISPC -\n");
2364
seq_printf(s, "dispc fclk source = %s\n",
2365
dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
2366
"dss1_alwon_fclk" : "dsi1_pll_fclk");
2422
seq_printf(s, "dispc fclk source = %s (%s)\n",
2423
dss_get_generic_clk_source_name(dispc_clk_src),
2424
dss_feat_get_clk_source_name(dispc_clk_src));
2368
2426
seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
2428
if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
2429
seq_printf(s, "- DISPC-CORE-CLK -\n");
2430
l = dispc_read_reg(DISPC_DIVISOR);
2431
lcd = FLD_GET(l, 23, 16);
2433
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2434
(dispc_fclk_rate()/lcd), lcd);
2370
2436
seq_printf(s, "- LCD1 -\n");
2438
lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD);
2440
seq_printf(s, "lcd1_clk source = %s (%s)\n",
2441
dss_get_generic_clk_source_name(lcd_clk_src),
2442
dss_feat_get_clk_source_name(lcd_clk_src));
2372
2444
dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
2374
2446
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2378
2450
if (dss_has_feature(FEAT_MGR_LCD2)) {
2379
2451
seq_printf(s, "- LCD2 -\n");
2453
lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2);
2455
seq_printf(s, "lcd2_clk source = %s (%s)\n",
2456
dss_get_generic_clk_source_name(lcd_clk_src),
2457
dss_feat_get_clk_source_name(lcd_clk_src));
2381
2459
dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
2383
2461
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2459
2537
DUMPREG(DISPC_TIMING_H(0));
2460
2538
DUMPREG(DISPC_TIMING_V(0));
2461
2539
DUMPREG(DISPC_POL_FREQ(0));
2462
DUMPREG(DISPC_DIVISOR(0));
2540
DUMPREG(DISPC_DIVISORo(0));
2463
2541
DUMPREG(DISPC_GLOBAL_ALPHA);
2464
2542
DUMPREG(DISPC_SIZE_DIG);
2465
2543
DUMPREG(DISPC_SIZE_LCD(0));
2714
2792
fck = dispc_fclk_rate();
2716
cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16);
2717
cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0);
2794
cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
2795
cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
2719
2797
cinfo->lck = fck / cinfo->lck_div;
2720
2798
cinfo->pck = cinfo->lck / cinfo->pck_div;
2866
2947
* but we presume they are on because we got an IRQ. However,
2867
2948
* an irq handler may turn the clocks off, so we may not have
2868
2949
* clock later in the function. */
2869
void dispc_irq_handler(void)
2950
static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
2953
u32 irqstatus, irqenable;
2873
2954
u32 handledirqs = 0;
2874
2955
u32 unhandled_errors;
2875
2956
struct omap_dispc_isr_data *isr_data;
2878
2959
spin_lock(&dispc.irq_lock);
2880
2961
irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
2962
irqenable = dispc_read_reg(DISPC_IRQENABLE);
2964
/* IRQ is not for us */
2965
if (!(irqstatus & irqenable)) {
2966
spin_unlock(&dispc.irq_lock);
2882
2970
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2883
2971
spin_lock(&dispc.irq_stats_lock);
3253
3343
l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
3254
3344
dispc_write_reg(DISPC_SYSCONFIG, l);
3346
/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
3347
if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
3348
l = dispc_read_reg(DISPC_DIVISOR);
3349
/* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
3350
l = FLD_MOD(l, 1, 0, 0);
3351
l = FLD_MOD(l, 1, 23, 16);
3352
dispc_write_reg(DISPC_DIVISOR, l);
3256
3355
/* FUNCGATED */
3257
3356
if (dss_has_feature(FEAT_FUNCGATED))
3258
3357
REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3269
3368
dispc_read_plane_fifo_sizes();
3272
int dispc_init(void)
3276
spin_lock_init(&dispc.irq_lock);
3278
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3279
spin_lock_init(&dispc.irq_stats_lock);
3280
dispc.irq_stats.last_reset = jiffies;
3283
INIT_WORK(&dispc.error_work, dispc_error_worker);
3285
dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
3287
DSSERR("can't ioremap DISPC\n");
3293
_omap_dispc_initial_config();
3295
_omap_dispc_initialize_irq();
3297
dispc_save_context();
3299
rev = dispc_read_reg(DISPC_REVISION);
3300
printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
3301
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3308
void dispc_exit(void)
3310
iounmap(dispc.base);
3313
3371
int dispc_enable_plane(enum omap_plane plane, bool enable)
3315
3373
DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
3421
/* DISPC HW IP initialisation */
3422
static int omap_dispchw_probe(struct platform_device *pdev)
3426
struct resource *dispc_mem;
3430
spin_lock_init(&dispc.irq_lock);
3432
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3433
spin_lock_init(&dispc.irq_stats_lock);
3434
dispc.irq_stats.last_reset = jiffies;
3437
INIT_WORK(&dispc.error_work, dispc_error_worker);
3439
dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
3441
DSSERR("can't get IORESOURCE_MEM DISPC\n");
3445
dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
3447
DSSERR("can't ioremap DISPC\n");
3451
dispc.irq = platform_get_irq(dispc.pdev, 0);
3452
if (dispc.irq < 0) {
3453
DSSERR("platform_get_irq failed\n");
3458
r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
3459
"OMAP DISPC", dispc.pdev);
3461
DSSERR("request_irq failed\n");
3467
_omap_dispc_initial_config();
3469
_omap_dispc_initialize_irq();
3471
dispc_save_context();
3473
rev = dispc_read_reg(DISPC_REVISION);
3474
dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
3475
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3481
iounmap(dispc.base);
3486
static int omap_dispchw_remove(struct platform_device *pdev)
3488
free_irq(dispc.irq, dispc.pdev);
3489
iounmap(dispc.base);
3493
static struct platform_driver omap_dispchw_driver = {
3494
.probe = omap_dispchw_probe,
3495
.remove = omap_dispchw_remove,
3497
.name = "omapdss_dispc",
3498
.owner = THIS_MODULE,
3502
int dispc_init_platform_driver(void)
3504
return platform_driver_register(&omap_dispchw_driver);
3507
void dispc_uninit_platform_driver(void)
3509
return platform_driver_unregister(&omap_dispchw_driver);