72
73
#define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400)
73
74
#define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404)
74
75
#define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408)
76
* Use DISPC_DIVISORo(ch) when DISPC_DIVISOR1 or DISPC_DIVISOR2 has to be
77
* configured. OMAP4 TRM uses DISPC_DIVISORo generically to refer DISPC_DIVISOR1
80
76
#define DISPC_DIVISORo(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
81
77
#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
82
78
#define DISPC_SIZE_DIG DISPC_REG(0x0078)
133
129
#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
136
* The OMAP4 DISPC_DIVISOR1 is backward compatible to OMAP3xxx DISPC_DIVISOR.
137
* However DISPC_DIVISOR is also provided in OMAP4, to control DISPC_CORE_CLK.
138
* This allows DISPC_CORE_CLK to be independent of logical clock dividers (lcd)
139
* of LCD1 (primary) and LCD2 (secondary) displays.
141
* To derive pixel clocks for Primary and Secondary LCD channels, configure the
142
* lcd and pcd in DISPC_DIVISOR1 and DISPC_DIVISOR2 respectively, using the
143
* DISPC_DIVISORo(ch).
145
131
#define DISPC_DIVISOR DISPC_REG(0x0804)
147
133
#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
1021
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);
1024
1025
static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
1151
1152
const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
1152
1153
DISPC_VID_ACCU0(1) };
1154
u8 hor_start, hor_end, vert_start, vert_end;
1154
1156
BUG_ON(plane == OMAP_DSS_GFX);
1156
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);
1157
1164
dispc_write_reg(ac0_reg[plane-1], val);
1163
1170
const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
1164
1171
DISPC_VID_ACCU1(1) };
1172
u8 hor_start, hor_end, vert_start, vert_end;
1166
1174
BUG_ON(plane == OMAP_DSS_GFX);
1168
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);
1169
1182
dispc_write_reg(ac1_reg[plane-1], val);
1203
1216
_dispc_set_fir(plane, fir_hinc, fir_vinc);
1205
1218
l = dispc_read_reg(dispc_reg_att[plane]);
1206
l &= ~((0x0f << 5) | (0x3 << 21));
1220
/* RESIZEENABLE and VERTICALTAPS */
1221
l &= ~((0x3 << 5) | (0x1 << 21));
1208
1222
l |= fir_hinc ? (1 << 5) : 0;
1209
1223
l |= fir_vinc ? (1 << 6) : 0;
1211
l |= hscaleup ? 0 : (1 << 7);
1212
l |= vscaleup ? 0 : (1 << 8);
1214
1224
l |= five_taps ? (1 << 21) : 0;
1215
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;
1217
1239
dispc_write_reg(dispc_reg_att[plane], l);
1275
REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
1277
1299
if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1278
REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
1280
REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
1282
REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
1283
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);
1287
1310
static int color_mode_to_bpp(enum omap_color_mode color_mode)
2333
2356
unsigned long r = 0;
2335
if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
2358
switch (dss_get_dispc_clk_source()) {
2359
case DSS_CLK_SRC_FCK:
2336
2360
r = dss_clk_get_rate(DSS_CLK_FCK);
2338
#ifdef CONFIG_OMAP2_DSS_DSI
2339
r = dsi_get_dsi1_pll_rate();
2362
case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2363
r = dsi_get_pll_hsdiv_dispc_rate();
2354
2380
lcd = FLD_GET(l, 23, 16);
2356
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();
2358
2393
return r / lcd;
2361
2396
unsigned long dispc_pclk_rate(enum omap_channel channel)
2364
2399
unsigned long r;
2367
2402
l = dispc_read_reg(DISPC_DIVISORo(channel));
2369
lcd = FLD_GET(l, 23, 16);
2370
2404
pcd = FLD_GET(l, 7, 0);
2372
r = dispc_fclk_rate();
2406
r = dispc_lclk_rate(channel);
2374
return r / lcd / pcd;
2377
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;
2381
2418
enable_clocks(1);
2383
2420
seq_printf(s, "- DISPC -\n");
2385
seq_printf(s, "dispc fclk source = %s\n",
2386
dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
2387
"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));
2389
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);
2391
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));
2393
2444
dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
2395
2446
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2399
2450
if (dss_has_feature(FEAT_MGR_LCD2)) {
2400
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));
2402
2459
dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
2404
2461
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2887
2947
* but we presume they are on because we got an IRQ. However,
2888
2948
* an irq handler may turn the clocks off, so we may not have
2889
2949
* clock later in the function. */
2890
void dispc_irq_handler(void)
2950
static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
2953
u32 irqstatus, irqenable;
2894
2954
u32 handledirqs = 0;
2895
2955
u32 unhandled_errors;
2896
2956
struct omap_dispc_isr_data *isr_data;
2899
2959
spin_lock(&dispc.irq_lock);
2901
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);
2903
2970
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2904
2971
spin_lock(&dispc.irq_stats_lock);
3369
3439
dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
3370
3440
if (!dispc_mem) {
3371
3441
DSSERR("can't get IORESOURCE_MEM DISPC\n");
3374
3445
dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
3375
3446
if (!dispc.base) {
3376
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");
3380
3465
enable_clocks(1);