| @@ -107,12 +107,27 @@ void sun4i_frontend_exit(struct sun4i_frontend *frontend) · 106 unmodified lines |
| 107 | } | 107 | } |
| 108 | EXPORT_SYMBOL(sun4i_frontend_exit); | 108 | EXPORT_SYMBOL(sun4i_frontend_exit); |
| 109 | | 109 | |
| | 110 | static bool sun4i_frontend_format_chroma_requires_swap(uint32_t fmt) |
| | 111 | { |
| | 112 | switch (fmt) { |
| | 113 | case DRM_FORMAT_YVU411: |
| | 114 | case DRM_FORMAT_YVU420: |
| | 115 | case DRM_FORMAT_YVU422: |
| | 116 | case DRM_FORMAT_YVU444: |
| | 117 | return true; |
| | 118 | |
| | 119 | default: |
| | 120 | return false; |
| | 121 | } |
| | 122 | } |
| | 123 | |
| 110 | void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, | 124 | void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, |
| 111 | struct drm_plane *plane) | 125 | struct drm_plane *plane) |
| 112 | { | 126 | { |
| 113 | struct drm_plane_state *state = plane->state; | 127 | struct drm_plane_state *state = plane->state; |
| 114 | struct drm_framebuffer *fb = state->fb; | 128 | struct drm_framebuffer *fb = state->fb; |
| 115 | dma_addr_t paddr; | 129 | dma_addr_t paddr; |
| | 130 | bool swap; |
| 116 | | 131 | |
| 117 | /* Set the line width */ | 132 | /* Set the line width */ |
| 118 | DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]); | 133 | DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]); |
| @@ -123,6 +138,13 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, · 4 unmodified lines |
| 123 | regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD1_REG, | 138 | regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD1_REG, |
| 124 | fb->pitches[1]); | 139 | fb->pitches[1]); |
| 125 | | 140 | |
| | 141 | if (fb->format->num_planes > 2) |
| | 142 | regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD2_REG, |
| | 143 | fb->pitches[2]); |
| | 144 | |
| | 145 | /* Some planar formats require chroma channel swapping by hand. */ |
| | 146 | swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format); |
| | 147 | |
| 126 | /* Set the physical address of the buffer in memory */ | 148 | /* Set the physical address of the buffer in memory */ |
| 127 | paddr = drm_fb_cma_get_gem_addr(fb, state, 0); | 149 | paddr = drm_fb_cma_get_gem_addr(fb, state, 0); |
| 128 | paddr -= PHYS_OFFSET; | 150 | paddr -= PHYS_OFFSET; |
| @@ -130,12 +152,20 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, · 1 unmodified line |
| 130 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); | 152 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); |
| 131 | | 153 | |
| 132 | if (fb->format->num_planes > 1) { | 154 | if (fb->format->num_planes > 1) { |
| 133 | paddr = drm_fb_cma_get_gem_addr(fb, state, 1); | 155 | paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1); |
| 134 | paddr -= PHYS_OFFSET; | 156 | paddr -= PHYS_OFFSET; |
| 135 | DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); | 157 | DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); |
| 136 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, | 158 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, |
| 137 | paddr); | 159 | paddr); |
| 138 | } | 160 | } |
| | 161 | |
| | 162 | if (fb->format->num_planes > 2) { |
| | 163 | paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2); |
| | 164 | paddr -= PHYS_OFFSET; |
| | 165 | DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr); |
| | 166 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG, |
| | 167 | paddr); |
| | 168 | } |
| 139 | } | 169 | } |
| 140 | EXPORT_SYMBOL(sun4i_frontend_update_buffer); | 170 | EXPORT_SYMBOL(sun4i_frontend_update_buffer); |
| 141 | | 171 | |
| @@ -145,10 +175,14 @@ sun4i_frontend_drm_format_to_input_fmt(const struct drm_format_info *format, · 3 unmodified lines |
| 145 | { | 175 | { |
| 146 | if (!format->is_yuv) | 176 | if (!format->is_yuv) |
| 147 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB; | 177 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB; |
| | 178 | else if (drm_format_info_is_yuv_sampling_411(format)) |
| | 179 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV411; |
| 148 | else if (drm_format_info_is_yuv_sampling_420(format)) | 180 | else if (drm_format_info_is_yuv_sampling_420(format)) |
| 149 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420; | 181 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420; |
| 150 | else if (drm_format_info_is_yuv_sampling_422(format)) | 182 | else if (drm_format_info_is_yuv_sampling_422(format)) |
| 151 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422; | 183 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422; |
| | 184 | else if (drm_format_info_is_yuv_sampling_444(format)) |
| | 185 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV444; |
| 152 | else | 186 | else |
| 153 | return -EINVAL; | 187 | return -EINVAL; |
| 154 | | 188 | |
| @@ -168,6 +202,10 @@ sun4i_frontend_drm_format_to_input_mode(const struct drm_format_info *format, · 13 unmodified lines |
| 168 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_SEMIPLANAR; | 202 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_SEMIPLANAR; |
| 169 | return 0; | 203 | return 0; |
| 170 | | 204 | |
| | 205 | case 3: |
| | 206 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PLANAR; |
| | 207 | return 0; |
| | 208 | |
| 171 | default: | 209 | default: |
| 172 | return -EINVAL; | 210 | return -EINVAL; |
| 173 | } | 211 | } |
| @@ -177,6 +215,12 @@ static int · 3 unmodified lines |
| 177 | sun4i_frontend_drm_format_to_input_sequence(const struct drm_format_info *format, | 215 | sun4i_frontend_drm_format_to_input_sequence(const struct drm_format_info *format, |
| 178 | u32 *val) | 216 | u32 *val) |
| 179 | { | 217 | { |
| | 218 | /* Planar formats have an explicit input sequence. */ |
| | 219 | if (drm_format_info_is_yuv_planar(format)) { |
| | 220 | *val = 0; |
| | 221 | return 0; |
| | 222 | } |
| | 223 | |
| 180 | switch (format->format) { | 224 | switch (format->format) { |
| 181 | case DRM_FORMAT_BGRX8888: | 225 | case DRM_FORMAT_BGRX8888: |
| 182 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX; | 226 | *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX; |
| @@ -248,7 +292,15 @@ static const uint32_t sun4i_frontend_formats[] = { · 65 unmodified lines |
| 248 | DRM_FORMAT_UYVY, | 292 | DRM_FORMAT_UYVY, |
| 249 | DRM_FORMAT_VYUY, | 293 | DRM_FORMAT_VYUY, |
| 250 | DRM_FORMAT_XRGB8888, | 294 | DRM_FORMAT_XRGB8888, |
| | 295 | DRM_FORMAT_YUV411, |
| | 296 | DRM_FORMAT_YUV420, |
| | 297 | DRM_FORMAT_YUV422, |
| | 298 | DRM_FORMAT_YUV444, |
| 251 | DRM_FORMAT_YUYV, | 299 | DRM_FORMAT_YUYV, |
| | 300 | DRM_FORMAT_YVU411, |
| | 301 | DRM_FORMAT_YVU420, |
| | 302 | DRM_FORMAT_YVU422, |
| | 303 | DRM_FORMAT_YVU444, |
| 252 | DRM_FORMAT_YVYU, | 304 | DRM_FORMAT_YVYU, |
| 253 | }; | 305 | }; |
| 254 | | 306 | |