tangled
alpha
login
or
join now
tjh.dev
/
kernel
1
fork
atom
Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1
fork
atom
overview
issues
pulls
pipelines
Merge omapdss scaling fixes
Tomi Valkeinen
10 years ago
f778dad3
a9bd32a8
+116
-16
3 changed files
expand all
collapse all
unified
split
drivers
video
fbdev
omap2
dss
dispc.c
hdmi4.c
hdmi_wp.c
+99
-15
drivers/video/fbdev/omap2/dss/dispc.c
reviewed
···
96
96
bool mstandby_workaround:1;
97
97
98
98
bool set_max_preload:1;
99
99
+
100
100
+
/* PIXEL_INC is not added to the last pixel of a line */
101
101
+
bool last_pixel_inc_missing:1;
99
102
};
100
103
101
104
#define DISPC_MAX_NR_FIFOS 5
···
1745
1742
row_repeat = false;
1746
1743
}
1747
1744
1745
1745
+
/*
1746
1746
+
* OMAP4/5 Errata i631:
1747
1747
+
* NV12 in 1D mode must use ROTATION=1. Otherwise DSS will fetch extra
1748
1748
+
* rows beyond the framebuffer, which may cause OCP error.
1749
1749
+
*/
1750
1750
+
if (color_mode == OMAP_DSS_COLOR_NV12 &&
1751
1751
+
rotation_type != OMAP_DSS_ROT_TILER)
1752
1752
+
vidrot = 1;
1753
1753
+
1748
1754
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
1749
1755
if (dss_has_feature(FEAT_ROWREPEATENABLE))
1750
1756
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
···
2167
2155
if (height > out_height) {
2168
2156
unsigned int ppl = mgr_timings->x_res;
2169
2157
2170
2170
-
tmp = pclk * height * out_width;
2158
2158
+
tmp = (u64)pclk * height * out_width;
2171
2159
do_div(tmp, 2 * out_height * ppl);
2172
2160
core_clk = tmp;
2173
2161
···
2175
2163
if (ppl == out_width)
2176
2164
return 0;
2177
2165
2178
2178
-
tmp = pclk * (height - 2 * out_height) * out_width;
2166
2166
+
tmp = (u64)pclk * (height - 2 * out_height) * out_width;
2179
2167
do_div(tmp, 2 * out_height * (ppl - out_width));
2180
2168
core_clk = max_t(u32, core_clk, tmp);
2181
2169
}
2182
2170
}
2183
2171
2184
2172
if (width > out_width) {
2185
2185
-
tmp = pclk * width;
2173
2173
+
tmp = (u64)pclk * width;
2186
2174
do_div(tmp, out_width);
2187
2175
core_clk = max_t(u32, core_clk, tmp);
2188
2176
···
2280
2268
}
2281
2269
} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2282
2270
2271
2271
+
if (error) {
2272
2272
+
DSSERR("failed to find scaling settings\n");
2273
2273
+
return -EINVAL;
2274
2274
+
}
2275
2275
+
2283
2276
if (in_width > maxsinglelinewidth) {
2284
2277
DSSERR("Cannot scale max input width exceeded");
2285
2278
return -EINVAL;
···
2301
2284
{
2302
2285
int error;
2303
2286
u16 in_width, in_height;
2304
2304
-
int min_factor = min(*decim_x, *decim_y);
2305
2287
const int maxsinglelinewidth =
2306
2288
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2307
2289
···
2334
2318
error = (error || in_width > maxsinglelinewidth * 2 ||
2335
2319
(in_width > maxsinglelinewidth && *five_taps) ||
2336
2320
!*core_clk || *core_clk > dispc_core_clk_rate());
2337
2337
-
if (error) {
2338
2338
-
if (*decim_x == *decim_y) {
2339
2339
-
*decim_x = min_factor;
2340
2340
-
++*decim_y;
2321
2321
+
2322
2322
+
if (!error) {
2323
2323
+
/* verify that we're inside the limits of scaler */
2324
2324
+
if (in_width / 4 > out_width)
2325
2325
+
error = 1;
2326
2326
+
2327
2327
+
if (*five_taps) {
2328
2328
+
if (in_height / 4 > out_height)
2329
2329
+
error = 1;
2341
2330
} else {
2342
2342
-
swap(*decim_x, *decim_y);
2343
2343
-
if (*decim_x < *decim_y)
2344
2344
-
++*decim_x;
2331
2331
+
if (in_height / 2 > out_height)
2332
2332
+
error = 1;
2345
2333
}
2346
2334
}
2335
2335
+
2336
2336
+
if (error)
2337
2337
+
++*decim_y;
2347
2338
} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2348
2339
2349
2349
-
if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
2350
2350
-
height, out_width, out_height, *five_taps)) {
2340
2340
+
if (error) {
2341
2341
+
DSSERR("failed to find scaling settings\n");
2342
2342
+
return -EINVAL;
2343
2343
+
}
2344
2344
+
2345
2345
+
if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width,
2346
2346
+
in_height, out_width, out_height, *five_taps)) {
2351
2347
DSSERR("horizontal timing too tight\n");
2352
2348
return -EINVAL;
2353
2349
}
···
2418
2390
out_width, out_height, mem_to_mem);
2419
2391
return 0;
2420
2392
}
2393
2393
+
2394
2394
+
#define DIV_FRAC(dividend, divisor) \
2395
2395
+
((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100))
2421
2396
2422
2397
static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
2423
2398
enum omap_overlay_caps caps,
···
2481
2450
if (ret)
2482
2451
return ret;
2483
2452
2484
2484
-
DSSDBG("required core clk rate = %lu Hz\n", core_clk);
2485
2485
-
DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
2453
2453
+
DSSDBG("%dx%d -> %dx%d (%d.%02d x %d.%02d), decim %dx%d %dx%d (%d.%02d x %d.%02d), taps %d, req clk %lu, cur clk %lu\n",
2454
2454
+
width, height,
2455
2455
+
out_width, out_height,
2456
2456
+
out_width / width, DIV_FRAC(out_width, width),
2457
2457
+
out_height / height, DIV_FRAC(out_height, height),
2458
2458
+
2459
2459
+
decim_x, decim_y,
2460
2460
+
width / decim_x, height / decim_y,
2461
2461
+
out_width / (width / decim_x), DIV_FRAC(out_width, width / decim_x),
2462
2462
+
out_height / (height / decim_y), DIV_FRAC(out_height, height / decim_y),
2463
2463
+
2464
2464
+
*five_taps ? 5 : 3,
2465
2465
+
core_clk, dispc_core_clk_rate());
2486
2466
2487
2467
if (!core_clk || core_clk > dispc_core_clk_rate()) {
2488
2468
DSSERR("failed to set up scaling, "
···
2576
2534
if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER)
2577
2535
return -EINVAL;
2578
2536
2537
2537
+
switch (color_mode) {
2538
2538
+
case OMAP_DSS_COLOR_YUV2:
2539
2539
+
case OMAP_DSS_COLOR_UYVY:
2540
2540
+
case OMAP_DSS_COLOR_NV12:
2541
2541
+
if (in_width & 1) {
2542
2542
+
DSSERR("input width %d is not even for YUV format\n",
2543
2543
+
in_width);
2544
2544
+
return -EINVAL;
2545
2545
+
}
2546
2546
+
break;
2547
2547
+
2548
2548
+
default:
2549
2549
+
break;
2550
2550
+
}
2551
2551
+
2579
2552
out_width = out_width == 0 ? width : out_width;
2580
2553
out_height = out_height == 0 ? height : out_height;
2581
2554
···
2620
2563
2621
2564
in_width = in_width / x_predecim;
2622
2565
in_height = in_height / y_predecim;
2566
2566
+
2567
2567
+
if (x_predecim > 1 || y_predecim > 1)
2568
2568
+
DSSDBG("predecimation %d x %x, new input size %d x %d\n",
2569
2569
+
x_predecim, y_predecim, in_width, in_height);
2570
2570
+
2571
2571
+
switch (color_mode) {
2572
2572
+
case OMAP_DSS_COLOR_YUV2:
2573
2573
+
case OMAP_DSS_COLOR_UYVY:
2574
2574
+
case OMAP_DSS_COLOR_NV12:
2575
2575
+
if (in_width & 1) {
2576
2576
+
DSSDBG("predecimated input width is not even for YUV format\n");
2577
2577
+
DSSDBG("adjusting input width %d -> %d\n",
2578
2578
+
in_width, in_width & ~1);
2579
2579
+
2580
2580
+
in_width &= ~1;
2581
2581
+
}
2582
2582
+
break;
2583
2583
+
2584
2584
+
default:
2585
2585
+
break;
2586
2586
+
}
2623
2587
2624
2588
if (color_mode == OMAP_DSS_COLOR_YUV2 ||
2625
2589
color_mode == OMAP_DSS_COLOR_UYVY ||
···
2710
2632
dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
2711
2633
dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
2712
2634
}
2635
2635
+
2636
2636
+
if (dispc.feat->last_pixel_inc_missing)
2637
2637
+
row_inc += pix_inc - 1;
2713
2638
2714
2639
dispc_ovl_set_row_inc(plane, row_inc);
2715
2640
dispc_ovl_set_pix_inc(plane, pix_inc);
···
3791
3710
.num_fifos = 3,
3792
3711
.no_framedone_tv = true,
3793
3712
.set_max_preload = false,
3713
3713
+
.last_pixel_inc_missing = true,
3794
3714
};
3795
3715
3796
3716
static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
···
3812
3730
.num_fifos = 3,
3813
3731
.no_framedone_tv = true,
3814
3732
.set_max_preload = false,
3733
3733
+
.last_pixel_inc_missing = true,
3815
3734
};
3816
3735
3817
3736
static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
···
3833
3750
.num_fifos = 3,
3834
3751
.no_framedone_tv = true,
3835
3752
.set_max_preload = false,
3753
3753
+
.last_pixel_inc_missing = true,
3836
3754
};
3837
3755
3838
3756
static const struct dispc_features omap44xx_dispc_feats = {
+1
-1
drivers/video/fbdev/omap2/dss/hdmi4.c
reviewed
···
230
230
err_mgr_enable:
231
231
hdmi_wp_video_stop(&hdmi.wp);
232
232
err_vid_enable:
233
233
-
err_phy_cfg:
234
233
hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
235
234
err_phy_pwr:
235
235
+
err_phy_cfg:
236
236
err_pll_cfg:
237
237
dss_pll_disable(&hdmi.pll.pll);
238
238
err_pll_enable:
+16
drivers/video/fbdev/omap2/dss/hdmi_wp.c
reviewed
···
110
110
111
111
void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
112
112
{
113
113
+
int i;
114
114
+
115
115
+
hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE);
116
116
+
113
117
REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);
118
118
+
119
119
+
for (i = 0; i < 50; ++i) {
120
120
+
u32 v;
121
121
+
122
122
+
msleep(20);
123
123
+
124
124
+
v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW);
125
125
+
if (v & HDMI_IRQ_VIDEO_FRAME_DONE)
126
126
+
return;
127
127
+
}
128
128
+
129
129
+
DSSERR("no HDMI FRAMEDONE when disabling output\n");
114
130
}
115
131
116
132
void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,