aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/omap2/dss/dispc.c201
-rw-r--r--drivers/video/omap2/dss/dss.h3
-rw-r--r--drivers/video/omap2/dss/manager.c5
-rw-r--r--include/video/omapdss.h1
4 files changed, 176 insertions, 34 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 53c321c13827..7a9a2e7d9685 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -110,6 +110,18 @@ static struct {
110#endif 110#endif
111} dispc; 111} dispc;
112 112
113enum omap_color_component {
114 /* used for all color formats for OMAP3 and earlier
115 * and for RGB and Y color component on OMAP4
116 */
117 DISPC_COLOR_COMPONENT_RGB_Y = 1 << 0,
118 /* used for UV component for
119 * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12
120 * color formats on OMAP4
121 */
122 DISPC_COLOR_COMPONENT_UV = 1 << 1,
123};
124
113static void _omap_dispc_set_irqs(void); 125static void _omap_dispc_set_irqs(void);
114 126
115static inline void dispc_write_reg(const u16 idx, u32 val) 127static inline void dispc_write_reg(const u16 idx, u32 val)
@@ -574,7 +586,8 @@ static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
574} 586}
575 587
576static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, 588static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
577 int vscaleup, int five_taps) 589 int vscaleup, int five_taps,
590 enum omap_color_component color_comp)
578{ 591{
579 /* Coefficients for horizontal up-sampling */ 592 /* Coefficients for horizontal up-sampling */
580 static const struct dispc_h_coef coef_hup[8] = { 593 static const struct dispc_h_coef coef_hup[8] = {
@@ -672,8 +685,14 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
672 | FLD_VAL(v_coef[i].vc1, 23, 16) 685 | FLD_VAL(v_coef[i].vc1, 23, 16)
673 | FLD_VAL(v_coef[i].vc2, 31, 24); 686 | FLD_VAL(v_coef[i].vc2, 31, 24);
674 687
675 _dispc_write_firh_reg(plane, i, h); 688 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
676 _dispc_write_firhv_reg(plane, i, hv); 689 _dispc_write_firh_reg(plane, i, h);
690 _dispc_write_firhv_reg(plane, i, hv);
691 } else {
692 _dispc_write_firh2_reg(plane, i, h);
693 _dispc_write_firhv2_reg(plane, i, hv);
694 }
695
677 } 696 }
678 697
679 if (five_taps) { 698 if (five_taps) {
@@ -681,7 +700,10 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
681 u32 v; 700 u32 v;
682 v = FLD_VAL(v_coef[i].vc00, 7, 0) 701 v = FLD_VAL(v_coef[i].vc00, 7, 0)
683 | FLD_VAL(v_coef[i].vc22, 15, 8); 702 | FLD_VAL(v_coef[i].vc22, 15, 8);
684 _dispc_write_firv_reg(plane, i, v); 703 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
704 _dispc_write_firv_reg(plane, i, v);
705 else
706 _dispc_write_firv2_reg(plane, i, v);
685 } 707 }
686 } 708 }
687} 709}
@@ -1090,18 +1112,27 @@ void dispc_enable_fifomerge(bool enable)
1090 enable_clocks(0); 1112 enable_clocks(0);
1091} 1113}
1092 1114
1093static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) 1115static void _dispc_set_fir(enum omap_plane plane,
1116 int hinc, int vinc,
1117 enum omap_color_component color_comp)
1094{ 1118{
1095 u32 val; 1119 u32 val;
1096 u8 hinc_start, hinc_end, vinc_start, vinc_end;
1097 1120
1098 dss_feat_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end); 1121 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
1099 dss_feat_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end); 1122 u8 hinc_start, hinc_end, vinc_start, vinc_end;
1100 1123
1101 val = FLD_VAL(vinc, vinc_start, vinc_end) | 1124 dss_feat_get_reg_field(FEAT_REG_FIRHINC,
1102 FLD_VAL(hinc, hinc_start, hinc_end); 1125 &hinc_start, &hinc_end);
1126 dss_feat_get_reg_field(FEAT_REG_FIRVINC,
1127 &vinc_start, &vinc_end);
1128 val = FLD_VAL(vinc, vinc_start, vinc_end) |
1129 FLD_VAL(hinc, hinc_start, hinc_end);
1103 1130
1104 dispc_write_reg(DISPC_OVL_FIR(plane), val); 1131 dispc_write_reg(DISPC_OVL_FIR(plane), val);
1132 } else {
1133 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
1134 dispc_write_reg(DISPC_OVL_FIR2(plane), val);
1135 }
1105} 1136}
1106 1137
1107static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) 1138static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
@@ -1148,31 +1179,40 @@ static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
1148 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); 1179 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
1149} 1180}
1150 1181
1151static void _dispc_set_scaling(enum omap_plane plane, 1182static void _dispc_set_scale_param(enum omap_plane plane,
1152 u16 orig_width, u16 orig_height, 1183 u16 orig_width, u16 orig_height,
1153 u16 out_width, u16 out_height, 1184 u16 out_width, u16 out_height,
1154 bool ilace, bool five_taps, 1185 bool five_taps, u8 rotation,
1155 bool fieldmode) 1186 enum omap_color_component color_comp)
1156{ 1187{
1157 int fir_hinc; 1188 int fir_hinc, fir_vinc;
1158 int fir_vinc;
1159 int hscaleup, vscaleup; 1189 int hscaleup, vscaleup;
1160 int accu0 = 0;
1161 int accu1 = 0;
1162 u32 l;
1163
1164 BUG_ON(plane == OMAP_DSS_GFX);
1165 1190
1166 hscaleup = orig_width <= out_width; 1191 hscaleup = orig_width <= out_width;
1167 vscaleup = orig_height <= out_height; 1192 vscaleup = orig_height <= out_height;
1168 1193
1169 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); 1194 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp);
1170 1195
1171 fir_hinc = 1024 * orig_width / out_width; 1196 fir_hinc = 1024 * orig_width / out_width;
1172 fir_vinc = 1024 * orig_height / out_height; 1197 fir_vinc = 1024 * orig_height / out_height;
1173 1198
1174 _dispc_set_fir(plane, fir_hinc, fir_vinc); 1199 _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1200}
1201
1202static void _dispc_set_scaling_common(enum omap_plane plane,
1203 u16 orig_width, u16 orig_height,
1204 u16 out_width, u16 out_height,
1205 bool ilace, bool five_taps,
1206 bool fieldmode, enum omap_color_mode color_mode,
1207 u8 rotation)
1208{
1209 int accu0 = 0;
1210 int accu1 = 0;
1211 u32 l;
1175 1212
1213 _dispc_set_scale_param(plane, orig_width, orig_height,
1214 out_width, out_height, five_taps,
1215 rotation, DISPC_COLOR_COMPONENT_RGB_Y);
1176 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); 1216 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1177 1217
1178 /* RESIZEENABLE and VERTICALTAPS */ 1218 /* RESIZEENABLE and VERTICALTAPS */
@@ -1184,8 +1224,8 @@ static void _dispc_set_scaling(enum omap_plane plane,
1184 /* VRESIZECONF and HRESIZECONF */ 1224 /* VRESIZECONF and HRESIZECONF */
1185 if (dss_has_feature(FEAT_RESIZECONF)) { 1225 if (dss_has_feature(FEAT_RESIZECONF)) {
1186 l &= ~(0x3 << 7); 1226 l &= ~(0x3 << 7);
1187 l |= hscaleup ? 0 : (1 << 7); 1227 l |= (orig_width <= out_width) ? 0 : (1 << 7);
1188 l |= vscaleup ? 0 : (1 << 8); 1228 l |= (orig_height <= out_height) ? 0 : (1 << 8);
1189 } 1229 }
1190 1230
1191 /* LINEBUFFERSPLIT */ 1231 /* LINEBUFFERSPLIT */
@@ -1202,7 +1242,7 @@ static void _dispc_set_scaling(enum omap_plane plane,
1202 */ 1242 */
1203 if (ilace && !fieldmode) { 1243 if (ilace && !fieldmode) {
1204 accu1 = 0; 1244 accu1 = 0;
1205 accu0 = (fir_vinc / 2) & 0x3ff; 1245 accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff;
1206 if (accu0 >= 1024/2) { 1246 if (accu0 >= 1024/2) {
1207 accu1 = 1024/2; 1247 accu1 = 1024/2;
1208 accu0 -= accu1; 1248 accu0 -= accu1;
@@ -1213,6 +1253,93 @@ static void _dispc_set_scaling(enum omap_plane plane,
1213 _dispc_set_vid_accu1(plane, 0, accu1); 1253 _dispc_set_vid_accu1(plane, 0, accu1);
1214} 1254}
1215 1255
1256static void _dispc_set_scaling_uv(enum omap_plane plane,
1257 u16 orig_width, u16 orig_height,
1258 u16 out_width, u16 out_height,
1259 bool ilace, bool five_taps,
1260 bool fieldmode, enum omap_color_mode color_mode,
1261 u8 rotation)
1262{
1263 int scale_x = out_width != orig_width;
1264 int scale_y = out_height != orig_height;
1265
1266 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1267 return;
1268 if ((color_mode != OMAP_DSS_COLOR_YUV2 &&
1269 color_mode != OMAP_DSS_COLOR_UYVY &&
1270 color_mode != OMAP_DSS_COLOR_NV12)) {
1271 /* reset chroma resampling for RGB formats */
1272 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1273 return;
1274 }
1275 switch (color_mode) {
1276 case OMAP_DSS_COLOR_NV12:
1277 /* UV is subsampled by 2 vertically*/
1278 orig_height >>= 1;
1279 /* UV is subsampled by 2 horz.*/
1280 orig_width >>= 1;
1281 break;
1282 case OMAP_DSS_COLOR_YUV2:
1283 case OMAP_DSS_COLOR_UYVY:
1284 /*For YUV422 with 90/270 rotation,
1285 *we don't upsample chroma
1286 */
1287 if (rotation == OMAP_DSS_ROT_0 ||
1288 rotation == OMAP_DSS_ROT_180)
1289 /* UV is subsampled by 2 hrz*/
1290 orig_width >>= 1;
1291 /* must use FIR for YUV422 if rotated */
1292 if (rotation != OMAP_DSS_ROT_0)
1293 scale_x = scale_y = true;
1294 break;
1295 default:
1296 BUG();
1297 }
1298
1299 if (out_width != orig_width)
1300 scale_x = true;
1301 if (out_height != orig_height)
1302 scale_y = true;
1303
1304 _dispc_set_scale_param(plane, orig_width, orig_height,
1305 out_width, out_height, five_taps,
1306 rotation, DISPC_COLOR_COMPONENT_UV);
1307
1308 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1309 (scale_x || scale_y) ? 1 : 0, 8, 8);
1310 /* set H scaling */
1311 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1312 /* set V scaling */
1313 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1314
1315 _dispc_set_vid_accu2_0(plane, 0x80, 0);
1316 _dispc_set_vid_accu2_1(plane, 0x80, 0);
1317}
1318
1319static void _dispc_set_scaling(enum omap_plane plane,
1320 u16 orig_width, u16 orig_height,
1321 u16 out_width, u16 out_height,
1322 bool ilace, bool five_taps,
1323 bool fieldmode, enum omap_color_mode color_mode,
1324 u8 rotation)
1325{
1326 BUG_ON(plane == OMAP_DSS_GFX);
1327
1328 _dispc_set_scaling_common(plane,
1329 orig_width, orig_height,
1330 out_width, out_height,
1331 ilace, five_taps,
1332 fieldmode, color_mode,
1333 rotation);
1334
1335 _dispc_set_scaling_uv(plane,
1336 orig_width, orig_height,
1337 out_width, out_height,
1338 ilace, five_taps,
1339 fieldmode, color_mode,
1340 rotation);
1341}
1342
1216static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, 1343static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1217 bool mirroring, enum omap_color_mode color_mode) 1344 bool mirroring, enum omap_color_mode color_mode)
1218{ 1345{
@@ -1619,7 +1746,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
1619 enum omap_dss_rotation_type rotation_type, 1746 enum omap_dss_rotation_type rotation_type,
1620 u8 rotation, int mirror, 1747 u8 rotation, int mirror,
1621 u8 global_alpha, u8 pre_mult_alpha, 1748 u8 global_alpha, u8 pre_mult_alpha,
1622 enum omap_channel channel) 1749 enum omap_channel channel, u32 puv_addr)
1623{ 1750{
1624 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; 1751 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
1625 bool five_taps = 0; 1752 bool five_taps = 0;
@@ -1668,7 +1795,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
1668 return -EINVAL; 1795 return -EINVAL;
1669 1796
1670 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1797 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1671 color_mode == OMAP_DSS_COLOR_UYVY) 1798 color_mode == OMAP_DSS_COLOR_UYVY ||
1799 color_mode == OMAP_DSS_COLOR_NV12)
1672 cconv = 1; 1800 cconv = 1;
1673 1801
1674 /* Must use 5-tap filter? */ 1802 /* Must use 5-tap filter? */
@@ -1742,6 +1870,12 @@ static int _dispc_setup_plane(enum omap_plane plane,
1742 _dispc_set_plane_ba0(plane, paddr + offset0); 1870 _dispc_set_plane_ba0(plane, paddr + offset0);
1743 _dispc_set_plane_ba1(plane, paddr + offset1); 1871 _dispc_set_plane_ba1(plane, paddr + offset1);
1744 1872
1873 if (OMAP_DSS_COLOR_NV12 == color_mode) {
1874 _dispc_set_plane_ba0_uv(plane, puv_addr + offset0);
1875 _dispc_set_plane_ba1_uv(plane, puv_addr + offset1);
1876 }
1877
1878
1745 _dispc_set_row_inc(plane, row_inc); 1879 _dispc_set_row_inc(plane, row_inc);
1746 _dispc_set_pix_inc(plane, pix_inc); 1880 _dispc_set_pix_inc(plane, pix_inc);
1747 1881
@@ -1755,7 +1889,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
1755 if (plane != OMAP_DSS_GFX) { 1889 if (plane != OMAP_DSS_GFX) {
1756 _dispc_set_scaling(plane, width, height, 1890 _dispc_set_scaling(plane, width, height,
1757 out_width, out_height, 1891 out_width, out_height,
1758 ilace, five_taps, fieldmode); 1892 ilace, five_taps, fieldmode,
1893 color_mode, rotation);
1759 _dispc_set_vid_size(plane, out_width, out_height); 1894 _dispc_set_vid_size(plane, out_width, out_height);
1760 _dispc_set_vid_color_conv(plane, cconv); 1895 _dispc_set_vid_color_conv(plane, cconv);
1761 } 1896 }
@@ -3439,11 +3574,12 @@ int dispc_setup_plane(enum omap_plane plane,
3439 bool ilace, 3574 bool ilace,
3440 enum omap_dss_rotation_type rotation_type, 3575 enum omap_dss_rotation_type rotation_type,
3441 u8 rotation, bool mirror, u8 global_alpha, 3576 u8 rotation, bool mirror, u8 global_alpha,
3442 u8 pre_mult_alpha, enum omap_channel channel) 3577 u8 pre_mult_alpha, enum omap_channel channel,
3578 u32 puv_addr)
3443{ 3579{
3444 int r = 0; 3580 int r = 0;
3445 3581
3446 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " 3582 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
3447 "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", 3583 "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
3448 plane, paddr, screen_width, pos_x, pos_y, 3584 plane, paddr, screen_width, pos_x, pos_y,
3449 width, height, 3585 width, height,
@@ -3462,7 +3598,8 @@ int dispc_setup_plane(enum omap_plane plane,
3462 rotation_type, 3598 rotation_type,
3463 rotation, mirror, 3599 rotation, mirror,
3464 global_alpha, 3600 global_alpha,
3465 pre_mult_alpha, channel); 3601 pre_mult_alpha,
3602 channel, puv_addr);
3466 3603
3467 enable_clocks(0); 3604 enable_clocks(0);
3468 3605
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6386f6b2b891..8ab6d43329bb 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -421,7 +421,8 @@ int dispc_setup_plane(enum omap_plane plane,
421 enum omap_dss_rotation_type rotation_type, 421 enum omap_dss_rotation_type rotation_type,
422 u8 rotation, bool mirror, 422 u8 rotation, bool mirror,
423 u8 global_alpha, u8 pre_mult_alpha, 423 u8 global_alpha, u8 pre_mult_alpha,
424 enum omap_channel channel); 424 enum omap_channel channel,
425 u32 puv_addr);
425 426
426bool dispc_go_busy(enum omap_channel channel); 427bool dispc_go_busy(enum omap_channel channel);
427void dispc_go(enum omap_channel channel); 428void dispc_go(enum omap_channel channel);
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index b40fe3dc9875..9aeea50e33ff 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -393,6 +393,7 @@ struct overlay_cache_data {
393 393
394 u32 paddr; 394 u32 paddr;
395 void __iomem *vaddr; 395 void __iomem *vaddr;
396 u32 p_uv_addr; /* relevant for NV12 format only */
396 u16 screen_width; 397 u16 screen_width;
397 u16 width; 398 u16 width;
398 u16 height; 399 u16 height;
@@ -861,7 +862,8 @@ static int configure_overlay(enum omap_plane plane)
861 c->mirror, 862 c->mirror,
862 c->global_alpha, 863 c->global_alpha,
863 c->pre_mult_alpha, 864 c->pre_mult_alpha,
864 c->channel); 865 c->channel,
866 c->p_uv_addr);
865 867
866 if (r) { 868 if (r) {
867 /* this shouldn't happen */ 869 /* this shouldn't happen */
@@ -1276,6 +1278,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1276 1278
1277 oc->paddr = ovl->info.paddr; 1279 oc->paddr = ovl->info.paddr;
1278 oc->vaddr = ovl->info.vaddr; 1280 oc->vaddr = ovl->info.vaddr;
1281 oc->p_uv_addr = ovl->info.p_uv_addr;
1279 oc->screen_width = ovl->info.screen_width; 1282 oc->screen_width = ovl->info.screen_width;
1280 oc->width = ovl->info.width; 1283 oc->width = ovl->info.width;
1281 oc->height = ovl->info.height; 1284 oc->height = ovl->info.height;
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 5658b4b83db8..892b97f8e157 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -305,6 +305,7 @@ struct omap_overlay_info {
305 305
306 u32 paddr; 306 u32 paddr;
307 void __iomem *vaddr; 307 void __iomem *vaddr;
308 u32 p_uv_addr; /* for NV12 format */
308 u16 screen_width; 309 u16 screen_width;
309 u16 width; 310 u16 width;
310 u16 height; 311 u16 height;