/* * These coefficients are taken from the A33 BSP from Allwinner. * * The first three values of each row are coded as 13-bit signed fixed-point * numbers, with 10 bits for the fractional part. The fourth value is a * constant coded as a 14-bit signed fixed-point number with 4 bits for the * fractional part. * * The values in table order give the following colorspace translation: * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135 * R = 1.164 * Y + 1.596 * V - 222 * B = 1.164 * Y + 2.018 * U + 276 * * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255], * following the BT601 spec.
*/ const u32 sunxi_bt601_yuv2rgb_coef[12] = {
0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
0x000004a7, 0x00000000, 0x00000662, 0x00003211,
0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
};
EXPORT_SYMBOL(sunxi_bt601_yuv2rgb_coef);
staticvoid sun4i_frontend_scaler_init(struct sun4i_frontend *frontend)
{ int i;
if (frontend->data->has_coef_access_ctrl)
regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL,
SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL);
for (i = 0; i < 32; i++) {
regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i),
sun4i_frontend_horz_coef[2 * i]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZCOEF0_REG(i),
sun4i_frontend_horz_coef[2 * i]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF1_REG(i),
sun4i_frontend_horz_coef[2 * i + 1]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZCOEF1_REG(i),
sun4i_frontend_horz_coef[2 * i + 1]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTCOEF_REG(i),
sun4i_frontend_vert_coef[i]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTCOEF_REG(i),
sun4i_frontend_vert_coef[i]);
}
if (frontend->data->has_coef_rdy)
regmap_write_bits(frontend->regs,
SUN4I_FRONTEND_FRM_CTRL_REG,
SUN4I_FRONTEND_FRM_CTRL_COEF_RDY,
SUN4I_FRONTEND_FRM_CTRL_COEF_RDY);
}
int sun4i_frontend_init(struct sun4i_frontend *frontend)
{ return pm_runtime_get_sync(frontend->dev);
}
EXPORT_SYMBOL(sun4i_frontend_init);
staticbool sun4i_frontend_format_chroma_requires_swap(uint32_t fmt)
{ switch (fmt) { case DRM_FORMAT_YVU411: case DRM_FORMAT_YVU420: case DRM_FORMAT_YVU422: case DRM_FORMAT_YVU444: returntrue;
default: returnfalse;
}
}
staticbool sun4i_frontend_format_supports_tiling(uint32_t fmt)
{ switch (fmt) { case DRM_FORMAT_NV12: case DRM_FORMAT_NV16: case DRM_FORMAT_NV21: case DRM_FORMAT_NV61: case DRM_FORMAT_YUV411: case DRM_FORMAT_YUV420: case DRM_FORMAT_YUV422: case DRM_FORMAT_YVU420: case DRM_FORMAT_YVU422: case DRM_FORMAT_YVU411: returntrue;
/* * The X1 offset is the offset to the bottom-right point in the * end tile, which is the final pixel (at offset width - 1) * within the end tile (with a 32-byte mask).
*/
offset = (width - 1) & (32 - 1);
if (fb->format->num_planes > 1)
strides[1] = fb->pitches[1];
if (fb->format->num_planes > 2)
strides[2] = fb->pitches[2];
}
/* Set the line width */
DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]);
regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD0_REG,
strides[0]);
if (fb->format->num_planes > 1)
regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD1_REG,
strides[1]);
if (fb->format->num_planes > 2)
regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD2_REG,
strides[2]);
/* Some planar formats require chroma channel swapping by hand. */
swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format);
/* Set the physical address of the buffer in memory */
dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0);
DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &dma_addr);
regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, dma_addr);
ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val); if (ret) {
DRM_DEBUG_DRIVER("Invalid input format\n"); return ret;
}
ret = sun4i_frontend_drm_format_to_input_mode(format, modifier,
&in_mod_val); if (ret) {
DRM_DEBUG_DRIVER("Invalid input mode\n"); return ret;
}
ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val); if (ret) {
DRM_DEBUG_DRIVER("Invalid pixel sequence\n"); return ret;
}
ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val); if (ret) {
DRM_DEBUG_DRIVER("Invalid output format\n"); return ret;
}
/* * I have no idea what this does exactly, but it seems to be * related to the scaler FIR filter phase parameters.
*/
ch1_phase_idx = (format->num_planes > 1) ? 1 : 0;
regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG,
frontend->data->ch_phase[0]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG,
frontend->data->ch_phase[ch1_phase_idx]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG,
frontend->data->ch_phase[0]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG,
frontend->data->ch_phase[ch1_phase_idx]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG,
frontend->data->ch_phase[0]);
regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG,
frontend->data->ch_phase[ch1_phase_idx]);
/* * Checking the input format is sufficient since we currently only * support RGB output formats to the backend. If YUV output formats * ever get supported, an YUV input and output would require bypassing * the CSC engine too.
*/ if (format->is_yuv) { /* Setup the CSC engine for YUV to RGB conversion. */
bypass = 0;
for (i = 0; i < ARRAY_SIZE(sunxi_bt601_yuv2rgb_coef); i++)
regmap_write(frontend->regs,
SUN4I_FRONTEND_CSC_COEF_REG(i),
sunxi_bt601_yuv2rgb_coef[i]);
} else {
bypass = SUN4I_FRONTEND_BYPASS_CSC_EN;
}
/* * TODO: It look like the A31 and A80 at least will need the * bit 7 (ALPHA_EN) enabled when using a format with alpha (so * ARGB8888).
*/
regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG,
out_fmt_val);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.