aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmber Jain <amber@ti.com>2011-05-19 10:17:54 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-05-23 01:29:47 -0400
commit0d66cbb53eca4ab3db85d9189d5a85c9fac49b84 (patch)
tree7941f147f00df90c7beb7e34b064fea3cb09f564
parentab5ca071e231e6d6da5f6aa9484a2cd233f7c746 (diff)
OMAP: DSS2: Add support for NV12 format
Add the support for NV12 color format. Configure base address for UV component of NV12 color format. Change the way chroma scaling is handled for YUV formats on OMAP4 by enabling chroma-resampling for video pipeline and hence using FIR2 register set for scaling UV. Changes to _dispc_set_scaling(), because of the reason above, are: - call _dispc_set_scaling_common() to handle scaling for all color formats except for OMAP4 where it only handles scaling for RGB or Y-component - call _dispc_set_scaling_uv() for special handling required for UV component on OMAP4. - dispc_set_scaling_uv() also resets chroma-resampling bit for RGB color modes. Contains chroma scaling (_dispc_set_scaling_uv) design and implemented by Lajos Molnar <molnar@ti.com> Signed-off-by: Amber Jain <amber@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-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;