#include "rockchip_drm_gem.h"
#include "rockchip_drm_fb.h"
#include "rockchip_drm_vop.h"
+#include "rockchip_drm_backlight.h"
#define VOP_REG_SUPPORT(vop, reg) \
(!reg.major || (reg.major == VOP_MAJOR(vop->data->version) && \
static void vop_initial(struct drm_crtc *crtc)
{
struct vop *vop = to_vop(crtc);
+ uint32_t irqs;
int i;
vop_power_enable(crtc);
VOP_WIN_SET(vop, win, gate, 1);
}
VOP_CTRL_SET(vop, afbdc_en, 0);
+
+ irqs = BUS_ERROR_INTR | WIN0_EMPTY_INTR | WIN1_EMPTY_INTR |
+ WIN2_EMPTY_INTR | WIN3_EMPTY_INTR | HWC_EMPTY_INTR |
+ POST_BUF_EMPTY_INTR;
+ VOP_INTR_SET_TYPE(vop, clear, irqs, 1);
+ VOP_INTR_SET_TYPE(vop, enable, irqs, 1);
}
static void vop_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&vop->vop_lock);
vop_initial(crtc);
- val = BIT(DCLK_INVERT);
- val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ?
+ VOP_CTRL_SET(vop, dclk_pol, 1);
+ val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ?
0 : BIT(HSYNC_POSITIVE);
val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ?
0 : BIT(VSYNC_POSITIVE);
case DRM_MODE_CONNECTOR_LVDS:
VOP_CTRL_SET(vop, rgb_en, 1);
VOP_CTRL_SET(vop, rgb_pin_pol, val);
+ VOP_CTRL_SET(vop, rgb_dclk_pol, 1);
+ VOP_CTRL_SET(vop, lvds_en, 1);
+ VOP_CTRL_SET(vop, lvds_pin_pol, val);
+ VOP_CTRL_SET(vop, lvds_dclk_pol, 1);
break;
case DRM_MODE_CONNECTOR_eDP:
VOP_CTRL_SET(vop, edp_en, 1);
VOP_CTRL_SET(vop, edp_pin_pol, val);
+ VOP_CTRL_SET(vop, edp_dclk_pol, 1);
break;
case DRM_MODE_CONNECTOR_HDMIA:
VOP_CTRL_SET(vop, hdmi_en, 1);
VOP_CTRL_SET(vop, hdmi_pin_pol, val);
+ VOP_CTRL_SET(vop, hdmi_dclk_pol, 1);
break;
case DRM_MODE_CONNECTOR_DSI:
VOP_CTRL_SET(vop, mipi_en, 1);
VOP_CTRL_SET(vop, mipi_pin_pol, val);
+ VOP_CTRL_SET(vop, mipi_dclk_pol, 1);
break;
case DRM_MODE_CONNECTOR_DisplayPort:
- val &= ~BIT(DCLK_INVERT);
+ VOP_CTRL_SET(vop, dp_dclk_pol, 0);
VOP_CTRL_SET(vop, dp_pin_pol, val);
VOP_CTRL_SET(vop, dp_en, 1);
break;
s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0);
VOP_CTRL_SET(vop, overlay_mode, is_yuv_output(s->bus_format));
VOP_CTRL_SET(vop, dsp_out_yuv, is_yuv_output(s->bus_format));
- VOP_CTRL_SET(vop, dsp_background,
- is_yuv_output(s->bus_format) ? 0x20010200 : 0);
+ /*
+ * Background color is 10bit depth if vop version >= 3.5
+ */
+ if (!is_yuv_output(s->bus_format))
+ val = 0;
+ else if (VOP_MAJOR(vop->data->version) == 3 &&
+ VOP_MINOR(vop->data->version) >= 5)
+ val = 0x20010200;
+ else
+ val = 0x801080;
+ VOP_CTRL_SET(vop, dsp_background, val);
VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
val = hact_st << 16;
val |= hact_end;
val = scl_cal_scale2(vdisplay, vsize) << 16;
val |= scl_cal_scale2(hdisplay, hsize);
VOP_CTRL_SET(vop, post_scl_factor, val);
- VOP_CTRL_SET(vop, post_scl_ctrl, 0x3);
+
+#define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0)
+#define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1)
+ VOP_CTRL_SET(vop, post_scl_ctrl,
+ POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) ||
+ POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
u16 vact_st_f1 = vtotal + vact_st + 1;
u16 vact_end_f1 = vact_st_f1 + vsize;
ret = IRQ_HANDLED;
}
+#define ERROR_HANDLER(x) \
+ do { \
+ if (active_irqs & x##_INTR) {\
+ DRM_DEV_ERROR_RATELIMITED(vop->dev, #x " irq err\n"); \
+ active_irqs &= ~x##_INTR; \
+ ret = IRQ_HANDLED; \
+ } \
+ } while (0)
+
+ ERROR_HANDLER(BUS_ERROR);
+ ERROR_HANDLER(WIN0_EMPTY);
+ ERROR_HANDLER(WIN1_EMPTY);
+ ERROR_HANDLER(WIN2_EMPTY);
+ ERROR_HANDLER(WIN3_EMPTY);
+ ERROR_HANDLER(HWC_EMPTY);
+ ERROR_HANDLER(POST_BUF_EMPTY);
+
/* Unhandled irqs are spurious. */
if (active_irqs)
DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs);
}
EXPORT_SYMBOL(rockchip_drm_register_notifier_to_dmc);
+static void vop_backlight_config_done(struct device *dev, bool async)
+{
+ struct vop *vop = dev_get_drvdata(dev);
+
+ if (vop && vop->is_enabled) {
+ int dle;
+
+ vop_cfg_done(vop);
+ if (!async) {
+ #define CTRL_GET(name) VOP_CTRL_GET(vop, name)
+ readx_poll_timeout(CTRL_GET, cfg_done,
+ dle, !dle, 5, 33333);
+ #undef CTRL_GET
+ }
+ }
+}
+
+static const struct rockchip_sub_backlight_ops rockchip_sub_backlight_ops = {
+ .config_done = vop_backlight_config_done,
+};
+
static int vop_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
pm_runtime_enable(&pdev->dev);
+ of_rockchip_drm_sub_backlight_register(dev, &vop->crtc,
+ &rockchip_sub_backlight_ops);
+
dmc_vop = vop;
return 0;