drm: i915 gvt, amdgpu, ast, rcar-du, meson + core fixes.

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJcAKgKAAoJEAx081l5xIa+0PgP/A+2bvrs6EgLQHAmdyJtuAzp
 /qeip9RtQG15rmgkzYucRgeTqmIwDHduCJDp7TcJ94Lial2FzBH5o8gRfqcOatgg
 Ury7/MwAOEg4omYxpuRP1qlZkK0wkEZiDT5aWYlYRFZI1+qsL28vdYyA1KflBNLS
 ZbGGB1DOIjtT1NGG4/cMGTd8iGM8cQIDzeKra6ZlTdDA3fARLBrf4bQCuphu7Eqv
 z2n0ZSEmGlvOWEAE4GR3nG3Uu32F6wCKdwWRG+/GLhRRFb8GdXZ3uriZXswdMNwt
 I1pIgHGHcpAGqD6IyHKtoBPlBs1Xs+VL1QwqHkN5hGniF32szBpCKOAPIxhLfJ7w
 S6clk/kauzdlzOI/t31LjKLME9a/mn95wxzridNTv2SmksEmNoNhvsEeXEoMjs2m
 s4CcJTyt5tbRqwXlWQg5DWkBAyNqNI1EkoDJRmefN+rW33m6x79r0RFcv57E8Sbs
 VyaLelyNyOcPm8Tqanko5o9RTQ56sZTNR4aOXVVrxSOBa7iJnK+h/kMeCn8TJDsT
 i8ftCzpco5uycxDgunw+lPoj9rnzuB7i2MgbEb2rOz3Mj8TH/WQnb1YWlUWPejuG
 ClAVjwWJAEy26MdGpMy0XUVtvgJK0h5hvnSA9yXAZjkJzA8LtbV82Nexu2MsEt02
 DiTPOpSgtSyxC4CLZ2G3
 =2Pvh
 -----END PGP SIGNATURE-----

Merge tag 'drm-fixes-2018-11-30' of git://anongit.freedesktop.org/drm/drm

Pull drm fixes from Dave Airlie:
 "This weeks instalment of fixes. Looks fairly like business as usual
  and everything seems to rolling along. There was one MST fix applied
  and reverted in the misc tree, but otherwise nothing too strange in
  here.

  core:
   - incorrect master setting on error fix

  i915:
   - only GVT fixes this week:
      * one MOCS register load
      * rpm lock fix
      * use after free

  rcar-du:
   - regression fix for group start

  amdgpu:
   - DP MST fix
   - GPUVM fix for huge pages
   - RLC fix for vega20

  ast:
   - fix EDID reading stability
   - ioreg free fix

  meson:
   - sleep in irq fix
   - vblank fixes
   - array boundary fix"

* tag 'drm-fixes-2018-11-30' of git://anongit.freedesktop.org/drm/drm:
  drm/ast: fixed reading monitor EDID not stable issue
  drm/ast: Fix incorrect free on ioregs
  Revert "drm/dp_mst: Skip validating ports during destruction, just ref"
  drm/amdgpu: Add delay after enable RLC ucode
  drm/amdgpu: Avoid endless loop in GPUVM fragment processing
  drm/amdgpu: Cast to uint64_t before left shift
  drm/meson: add support for 1080p25 mode
  drm/meson: Fix OOB memory accesses in meson_viu_set_osd_lut()
  drm/meson: Enable fast_io in meson_dw_hdmi_regmap_config
  drm/meson: Fixes for drm_crtc_vblank_on/off support
  drm: set is_master to 0 upon drm_new_set_master() failure
  drm/dp_mst: Skip validating ports during destruction, just ref
  drm: rcar-du: Fix DU3 start/stop on M3-N
  drm/amd/dm: Understand why attaching path/tile properties are needed
  drm/amd/dm: Don't forget to attach MST encoders
  drm/i915/gvt: Avoid use-after-free iterating the gtt list
  drm/i915/gvt: ensure gpu is powered before do i915_gem_gtt_insert
  drm/i915/gvt: not to touch undefined MOCS registers
This commit is contained in:
Linus Torvalds 2018-11-30 09:10:29 -08:00
commit 570a37437c
14 changed files with 110 additions and 33 deletions

View File

@ -181,7 +181,7 @@ static unsigned amdgpu_vm_num_entries(struct amdgpu_device *adev,
if (level == adev->vm_manager.root_level) if (level == adev->vm_manager.root_level)
/* For the root directory */ /* For the root directory */
return round_up(adev->vm_manager.max_pfn, 1 << shift) >> shift; return round_up(adev->vm_manager.max_pfn, 1ULL << shift) >> shift;
else if (level != AMDGPU_VM_PTB) else if (level != AMDGPU_VM_PTB)
/* Everything in between */ /* Everything in between */
return 512; return 512;
@ -1656,9 +1656,11 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
if (!amdgpu_vm_pt_descendant(adev, &cursor)) if (!amdgpu_vm_pt_descendant(adev, &cursor))
return -ENOENT; return -ENOENT;
continue; continue;
} else if (frag >= parent_shift) { } else if (frag >= parent_shift &&
cursor.level - 1 != adev->vm_manager.root_level) {
/* If the fragment size is even larger than the parent /* If the fragment size is even larger than the parent
* shift we should go up one level and check it again. * shift we should go up one level and check it again
* unless one level up is the root level.
*/ */
if (!amdgpu_vm_pt_ancestor(&cursor)) if (!amdgpu_vm_pt_ancestor(&cursor))
return -ENOENT; return -ENOENT;
@ -1666,10 +1668,10 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
} }
/* Looks good so far, calculate parameters for the update */ /* Looks good so far, calculate parameters for the update */
incr = AMDGPU_GPU_PAGE_SIZE << shift; incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift;
mask = amdgpu_vm_entries_mask(adev, cursor.level); mask = amdgpu_vm_entries_mask(adev, cursor.level);
pe_start = ((cursor.pfn >> shift) & mask) * 8; pe_start = ((cursor.pfn >> shift) & mask) * 8;
entry_end = (mask + 1) << shift; entry_end = (uint64_t)(mask + 1) << shift;
entry_end += cursor.pfn & ~(entry_end - 1); entry_end += cursor.pfn & ~(entry_end - 1);
entry_end = min(entry_end, end); entry_end = min(entry_end, end);
@ -1682,7 +1684,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
flags | AMDGPU_PTE_FRAG(frag)); flags | AMDGPU_PTE_FRAG(frag));
pe_start += nptes * 8; pe_start += nptes * 8;
dst += nptes * AMDGPU_GPU_PAGE_SIZE << shift; dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift;
frag_start = upd_end; frag_start = upd_end;
if (frag_start >= frag_end) { if (frag_start >= frag_end) {

View File

@ -2440,12 +2440,13 @@ static void gfx_v9_0_rlc_start(struct amdgpu_device *adev)
#endif #endif
WREG32_FIELD15(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 1); WREG32_FIELD15(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 1);
udelay(50);
/* carrizo do enable cp interrupt after cp inited */ /* carrizo do enable cp interrupt after cp inited */
if (!(adev->flags & AMD_IS_APU)) if (!(adev->flags & AMD_IS_APU)) {
gfx_v9_0_enable_gui_idle_interrupt(adev, true); gfx_v9_0_enable_gui_idle_interrupt(adev, true);
udelay(50);
udelay(50); }
#ifdef AMDGPU_RLC_DEBUG_RETRY #ifdef AMDGPU_RLC_DEBUG_RETRY
/* RLC_GPM_GENERAL_6 : RLC Ucode version */ /* RLC_GPM_GENERAL_6 : RLC Ucode version */

View File

@ -342,10 +342,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
master->connector_id); master->connector_id);
aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master); aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
drm_connector_attach_encoder(&aconnector->base,
&aconnector->mst_encoder->base);
/*
* TODO: understand why this one is needed
*/
drm_object_attach_property( drm_object_attach_property(
&connector->base, &connector->base,
dev->mode_config.path_property, dev->mode_config.path_property,

View File

@ -583,7 +583,8 @@ void ast_driver_unload(struct drm_device *dev)
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);
ast_mm_fini(ast); ast_mm_fini(ast);
pci_iounmap(dev->pdev, ast->ioregs); if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET)
pci_iounmap(dev->pdev, ast->ioregs);
pci_iounmap(dev->pdev, ast->regs); pci_iounmap(dev->pdev, ast->regs);
kfree(ast); kfree(ast);
} }

View File

@ -973,9 +973,21 @@ static int get_clock(void *i2c_priv)
{ {
struct ast_i2c_chan *i2c = i2c_priv; struct ast_i2c_chan *i2c = i2c_priv;
struct ast_private *ast = i2c->dev->dev_private; struct ast_private *ast = i2c->dev->dev_private;
uint32_t val; uint32_t val, val2, count, pass;
count = 0;
pass = 0;
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
do {
val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
if (val == val2) {
pass++;
} else {
pass = 0;
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
}
} while ((pass < 5) && (count++ < 0x10000));
val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4;
return val & 1 ? 1 : 0; return val & 1 ? 1 : 0;
} }
@ -983,9 +995,21 @@ static int get_data(void *i2c_priv)
{ {
struct ast_i2c_chan *i2c = i2c_priv; struct ast_i2c_chan *i2c = i2c_priv;
struct ast_private *ast = i2c->dev->dev_private; struct ast_private *ast = i2c->dev->dev_private;
uint32_t val; uint32_t val, val2, count, pass;
count = 0;
pass = 0;
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
do {
val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
if (val == val2) {
pass++;
} else {
pass = 0;
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
}
} while ((pass < 5) && (count++ < 0x10000));
val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5;
return val & 1 ? 1 : 0; return val & 1 ? 1 : 0;
} }
@ -998,7 +1022,7 @@ static void set_clock(void *i2c_priv, int clock)
for (i = 0; i < 0x10000; i++) { for (i = 0; i < 0x10000; i++) {
ujcrb7 = ((clock & 0x01) ? 0 : 1); ujcrb7 = ((clock & 0x01) ? 0 : 1);
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfe, ujcrb7); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01); jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
if (ujcrb7 == jtemp) if (ujcrb7 == jtemp)
break; break;
@ -1014,7 +1038,7 @@ static void set_data(void *i2c_priv, int data)
for (i = 0; i < 0x10000; i++) { for (i = 0; i < 0x10000; i++) {
ujcrb7 = ((data & 0x01) ? 0 : 1) << 2; ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfb, ujcrb7); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04); jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
if (ujcrb7 == jtemp) if (ujcrb7 == jtemp)
break; break;

View File

@ -142,6 +142,7 @@ static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
lockdep_assert_held_once(&dev->master_mutex); lockdep_assert_held_once(&dev->master_mutex);
WARN_ON(fpriv->is_master);
old_master = fpriv->master; old_master = fpriv->master;
fpriv->master = drm_master_create(dev); fpriv->master = drm_master_create(dev);
if (!fpriv->master) { if (!fpriv->master) {
@ -170,6 +171,7 @@ out_err:
/* drop references and restore old master on failure */ /* drop references and restore old master on failure */
drm_master_put(&fpriv->master); drm_master_put(&fpriv->master);
fpriv->master = old_master; fpriv->master = old_master;
fpriv->is_master = 0;
return ret; return ret;
} }

View File

@ -61,10 +61,12 @@ static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
} }
mutex_lock(&dev_priv->drm.struct_mutex); mutex_lock(&dev_priv->drm.struct_mutex);
mmio_hw_access_pre(dev_priv);
ret = i915_gem_gtt_insert(&dev_priv->ggtt.vm, node, ret = i915_gem_gtt_insert(&dev_priv->ggtt.vm, node,
size, I915_GTT_PAGE_SIZE, size, I915_GTT_PAGE_SIZE,
I915_COLOR_UNEVICTABLE, I915_COLOR_UNEVICTABLE,
start, end, flags); start, end, flags);
mmio_hw_access_post(dev_priv);
mutex_unlock(&dev_priv->drm.struct_mutex); mutex_unlock(&dev_priv->drm.struct_mutex);
if (ret) if (ret)
gvt_err("fail to alloc %s gm space from host\n", gvt_err("fail to alloc %s gm space from host\n",

View File

@ -2447,10 +2447,11 @@ static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu)
static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu) static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu)
{ {
struct intel_gvt_partial_pte *pos; struct intel_gvt_partial_pte *pos, *next;
list_for_each_entry(pos, list_for_each_entry_safe(pos, next,
&vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list, list) { &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list,
list) {
gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n", gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n",
pos->offset, pos->data); pos->offset, pos->data);
kfree(pos); kfree(pos);

View File

@ -158,6 +158,8 @@ static void load_render_mocs(struct drm_i915_private *dev_priv)
int ring_id, i; int ring_id, i;
for (ring_id = 0; ring_id < ARRAY_SIZE(regs); ring_id++) { for (ring_id = 0; ring_id < ARRAY_SIZE(regs); ring_id++) {
if (!HAS_ENGINE(dev_priv, ring_id))
continue;
offset.reg = regs[ring_id]; offset.reg = regs[ring_id];
for (i = 0; i < GEN9_MOCS_SIZE; i++) { for (i = 0; i < GEN9_MOCS_SIZE; i++) {
gen9_render_mocs.control_table[ring_id][i] = gen9_render_mocs.control_table[ring_id][i] =

View File

@ -45,6 +45,7 @@ struct meson_crtc {
struct drm_crtc base; struct drm_crtc base;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
struct meson_drm *priv; struct meson_drm *priv;
bool enabled;
}; };
#define to_meson_crtc(x) container_of(x, struct meson_crtc, base) #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
@ -80,8 +81,7 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
}; };
static void meson_crtc_atomic_enable(struct drm_crtc *crtc, static void meson_crtc_enable(struct drm_crtc *crtc)
struct drm_crtc_state *old_state)
{ {
struct meson_crtc *meson_crtc = to_meson_crtc(crtc); struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
struct drm_crtc_state *crtc_state = crtc->state; struct drm_crtc_state *crtc_state = crtc->state;
@ -101,6 +101,22 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE, writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
priv->io_base + _REG(VPP_MISC)); priv->io_base + _REG(VPP_MISC));
drm_crtc_vblank_on(crtc);
meson_crtc->enabled = true;
}
static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
struct meson_drm *priv = meson_crtc->priv;
DRM_DEBUG_DRIVER("\n");
if (!meson_crtc->enabled)
meson_crtc_enable(crtc);
priv->viu.osd1_enabled = true; priv->viu.osd1_enabled = true;
} }
@ -110,6 +126,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
struct meson_crtc *meson_crtc = to_meson_crtc(crtc); struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
struct meson_drm *priv = meson_crtc->priv; struct meson_drm *priv = meson_crtc->priv;
drm_crtc_vblank_off(crtc);
priv->viu.osd1_enabled = false; priv->viu.osd1_enabled = false;
priv->viu.osd1_commit = false; priv->viu.osd1_commit = false;
@ -124,6 +142,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
crtc->state->event = NULL; crtc->state->event = NULL;
} }
meson_crtc->enabled = false;
} }
static void meson_crtc_atomic_begin(struct drm_crtc *crtc, static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
@ -132,6 +152,9 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
struct meson_crtc *meson_crtc = to_meson_crtc(crtc); struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
unsigned long flags; unsigned long flags;
if (crtc->state->enable && !meson_crtc->enabled)
meson_crtc_enable(crtc);
if (crtc->state->event) { if (crtc->state->event) {
WARN_ON(drm_crtc_vblank_get(crtc) != 0); WARN_ON(drm_crtc_vblank_get(crtc) != 0);

View File

@ -706,6 +706,7 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {
.reg_read = meson_dw_hdmi_reg_read, .reg_read = meson_dw_hdmi_reg_read,
.reg_write = meson_dw_hdmi_reg_write, .reg_write = meson_dw_hdmi_reg_write,
.max_register = 0x10000, .max_register = 0x10000,
.fast_io = true,
}; };
static bool meson_hdmi_connector_is_available(struct device *dev) static bool meson_hdmi_connector_is_available(struct device *dev)

View File

@ -71,6 +71,7 @@
*/ */
/* HHI Registers */ /* HHI Registers */
#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
#define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */ #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
@ -714,6 +715,7 @@ struct meson_hdmi_venc_vic_mode {
{ 5, &meson_hdmi_encp_mode_1080i60 }, { 5, &meson_hdmi_encp_mode_1080i60 },
{ 20, &meson_hdmi_encp_mode_1080i50 }, { 20, &meson_hdmi_encp_mode_1080i50 },
{ 32, &meson_hdmi_encp_mode_1080p24 }, { 32, &meson_hdmi_encp_mode_1080p24 },
{ 33, &meson_hdmi_encp_mode_1080p50 },
{ 34, &meson_hdmi_encp_mode_1080p30 }, { 34, &meson_hdmi_encp_mode_1080p30 },
{ 31, &meson_hdmi_encp_mode_1080p50 }, { 31, &meson_hdmi_encp_mode_1080p50 },
{ 16, &meson_hdmi_encp_mode_1080p60 }, { 16, &meson_hdmi_encp_mode_1080p60 },
@ -1530,10 +1532,12 @@ unsigned int meson_venci_get_field(struct meson_drm *priv)
void meson_venc_enable_vsync(struct meson_drm *priv) void meson_venc_enable_vsync(struct meson_drm *priv)
{ {
writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL)); writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
} }
void meson_venc_disable_vsync(struct meson_drm *priv) void meson_venc_disable_vsync(struct meson_drm *priv)
{ {
regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 0);
writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL)); writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
} }

View File

@ -184,18 +184,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
if (lut_sel == VIU_LUT_OSD_OETF) { if (lut_sel == VIU_LUT_OSD_OETF) {
writel(0, priv->io_base + _REG(addr_port)); writel(0, priv->io_base + _REG(addr_port));
for (i = 0; i < 20; i++) for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));
writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16), writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));
for (i = 0; i < 20; i++) for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));
for (i = 0; i < 20; i++) for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));
@ -211,18 +211,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
} else if (lut_sel == VIU_LUT_OSD_EOTF) { } else if (lut_sel == VIU_LUT_OSD_EOTF) {
writel(0, priv->io_base + _REG(addr_port)); writel(0, priv->io_base + _REG(addr_port));
for (i = 0; i < 20; i++) for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));
writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16), writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));
for (i = 0; i < 20; i++) for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));
for (i = 0; i < 20; i++) for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
priv->io_base + _REG(data_port)); priv->io_base + _REG(data_port));

View File

@ -202,10 +202,25 @@ void rcar_du_group_put(struct rcar_du_group *rgrp)
static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
{ {
struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2]; struct rcar_du_device *rcdu = rgrp->dev;
rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN, /*
start ? DSYSR_DEN : DSYSR_DRES); * Group start/stop is controlled by the DRES and DEN bits of DSYSR0
* for the first group and DSYSR2 for the second group. On most DU
* instances, this maps to the first CRTC of the group, and we can just
* use rcar_du_crtc_dsysr_clr_set() to access the correct DSYSR. On
* M3-N, however, DU2 doesn't exist, but DSYSR2 does. We thus need to
* access the register directly using group read/write.
*/
if (rcdu->info->channels_mask & BIT(rgrp->index * 2)) {
struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
start ? DSYSR_DEN : DSYSR_DRES);
} else {
rcar_du_group_write(rgrp, DSYSR,
start ? DSYSR_DEN : DSYSR_DRES);
}
} }
void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)