@@ -119,11 +119,23 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD0_REG,
fb->pitches[0]);
+ if (fb->format->num_planes > 1)
+ regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD1_REG,
+ fb->pitches[1]);
+
/* Set the physical address of the buffer in memory */
paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
paddr -= PHYS_OFFSET;
- DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+ DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr);
regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
+
+ if (fb->format->num_planes > 1) {
+ paddr = drm_fb_cma_get_gem_addr(fb, state, 1);
+ paddr -= PHYS_OFFSET;
+ DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr);
+ regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG,
+ paddr);
+ }
}
EXPORT_SYMBOL(sun4i_frontend_update_buffer);
@@ -133,6 +145,8 @@ sun4i_frontend_drm_format_to_input_fmt(const struct drm_format_info *format,
{
if (!format->is_yuv)
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
+ else if (drm_format_info_is_yuv_sampling_420(format))
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420;
else if (drm_format_info_is_yuv_sampling_422(format))
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422;
else
@@ -145,12 +159,18 @@ static int
sun4i_frontend_drm_format_to_input_mode(const struct drm_format_info *format,
u32 *val)
{
- if (format->num_planes == 1)
+ switch (format->num_planes) {
+ case 1:
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED;
- else
- return -EINVAL;
+ return 0;
- return 0;
+ case 2:
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_SEMIPLANAR;
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
}
static int
@@ -162,6 +182,22 @@ sun4i_frontend_drm_format_to_input_sequence(const struct drm_format_info *format
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX;
return 0;
+ case DRM_FORMAT_NV12:
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV;
+ return 0;
+
+ case DRM_FORMAT_NV16:
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV;
+ return 0;
+
+ case DRM_FORMAT_NV21:
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU;
+ return 0;
+
+ case DRM_FORMAT_NV61:
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU;
+ return 0;
+
case DRM_FORMAT_UYVY:
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UYVY;
return 0;
@@ -205,6 +241,10 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
static const uint32_t sun4i_frontend_formats[] = {
DRM_FORMAT_BGRX8888,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV16,
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV61,
DRM_FORMAT_UYVY,
DRM_FORMAT_VYUY,
DRM_FORMAT_XRGB8888,
@@ -22,17 +22,23 @@
#define SUN4I_FRONTEND_BYPASS_CSC_EN BIT(1)
#define SUN4I_FRONTEND_BUF_ADDR0_REG 0x020
+#define SUN4I_FRONTEND_BUF_ADDR1_REG 0x024
#define SUN4I_FRONTEND_LINESTRD0_REG 0x040
+#define SUN4I_FRONTEND_LINESTRD1_REG 0x044
#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c
#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED (1 << 8)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_SEMIPLANAR (2 << 8)
#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422 (1 << 4)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420 (2 << 4)
#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB (5 << 4)
#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UYVY 0
#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YUYV 1
#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VYUY 2
#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YVYU 3
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV 0
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU 1
#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX 0
#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB 1
@@ -138,6 +138,10 @@ static const uint32_t sun4i_layer_formats[] = {
DRM_FORMAT_RGBA4444,
DRM_FORMAT_RGB888,
DRM_FORMAT_RGB565,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV16,
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV61,
DRM_FORMAT_UYVY,
DRM_FORMAT_VYUY,
DRM_FORMAT_XRGB8888,