Commit 6aa7a22b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drm-fixes-2019-06-14' of git://anongit.freedesktop.org/drm/drm

Pull drm fixes from Daniel Vetter:
 "Nothing unsettling here, also not aware of anything serious still
  pending.

  The edid override regression fix took a bit longer since this seems to
  be an area with an overabundance of bad options. But the fix we have
  now seems like a good path forward.

  Next week it should be back to Dave.

  Summary:

   - fix regression on amdgpu on SI

   - fix edid override regression

   - driver fixes: amdgpu, i915, mediatek, meson, panfrost

   - fix writecombine for vmap in gem-shmem helper (used by panfrost)

   - add more panel quirks"

* tag 'drm-fixes-2019-06-14' of git://anongit.freedesktop.org/drm/drm: (25 commits)
  drm/amdgpu: return 0 by default in amdgpu_pm_load_smu_firmware
  drm/amdgpu: Fix bounds checking in amdgpu_ras_is_supported()
  drm: add fallback override/firmware EDID modes workaround
  drm/edid: abstract override/firmware EDID retrieval
  drm/i915/perf: fix whitelist on Gen10+
  drm/i915/sdvo: Implement proper HDMI audio support for SDVO
  drm/i915: Fix per-pixel alpha with CCS
  drm/i915/dmc: protect against reading random memory
  drm/i915/dsi: Use a fuzzy check for burst mode clock check
  drm/amdgpu/{uvd,vcn}: fetch ring's read_ptr after alloc
  drm/panfrost: Require the simple_ondemand governor
  drm/panfrost: make devfreq optional again
  drm/gem_shmem: Use a writecombine mapping for ->vaddr
  drm: panel-orientation-quirks: Add quirk for GPD MicroPC
  drm: panel-orientation-quirks: Add quirk for GPD pocket2
  drm/meson: fix G12A primary plane disabling
  drm/meson: fix primary plane disabling
  drm/meson: fix G12A HDMI PLL settings for 4K60 1000/1001 variations
  drm/mediatek: call mtk_dsi_stop() after mtk_drm_crtc_atomic_disable()
  drm/mediatek: clear num_pipes when unbind driver
  ...
parents 40665244 e14c5873
...@@ -2492,7 +2492,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev) ...@@ -2492,7 +2492,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version)
{ {
int r = -EINVAL; int r;
if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) {
r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle);
...@@ -2502,7 +2502,7 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio ...@@ -2502,7 +2502,7 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio
} }
*smu_version = adev->pm.fw_version; *smu_version = adev->pm.fw_version;
} }
return r; return 0;
} }
int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
......
...@@ -172,6 +172,8 @@ static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev, ...@@ -172,6 +172,8 @@ static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev,
{ {
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
if (block >= AMDGPU_RAS_BLOCK_COUNT)
return 0;
return ras && (ras->supported & (1 << block)); return ras && (ras->supported & (1 << block));
} }
......
...@@ -594,7 +594,7 @@ int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout) ...@@ -594,7 +594,7 @@ int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring) int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
{ {
struct amdgpu_device *adev = ring->adev; struct amdgpu_device *adev = ring->adev;
uint32_t rptr = amdgpu_ring_get_rptr(ring); uint32_t rptr;
unsigned i; unsigned i;
int r; int r;
...@@ -602,6 +602,8 @@ int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring) ...@@ -602,6 +602,8 @@ int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
if (r) if (r)
return r; return r;
rptr = amdgpu_ring_get_rptr(ring);
amdgpu_ring_write(ring, VCN_ENC_CMD_END); amdgpu_ring_write(ring, VCN_ENC_CMD_END);
amdgpu_ring_commit(ring); amdgpu_ring_commit(ring);
......
...@@ -170,13 +170,16 @@ static void uvd_v6_0_enc_ring_set_wptr(struct amdgpu_ring *ring) ...@@ -170,13 +170,16 @@ static void uvd_v6_0_enc_ring_set_wptr(struct amdgpu_ring *ring)
static int uvd_v6_0_enc_ring_test_ring(struct amdgpu_ring *ring) static int uvd_v6_0_enc_ring_test_ring(struct amdgpu_ring *ring)
{ {
struct amdgpu_device *adev = ring->adev; struct amdgpu_device *adev = ring->adev;
uint32_t rptr = amdgpu_ring_get_rptr(ring); uint32_t rptr;
unsigned i; unsigned i;
int r; int r;
r = amdgpu_ring_alloc(ring, 16); r = amdgpu_ring_alloc(ring, 16);
if (r) if (r)
return r; return r;
rptr = amdgpu_ring_get_rptr(ring);
amdgpu_ring_write(ring, HEVC_ENC_CMD_END); amdgpu_ring_write(ring, HEVC_ENC_CMD_END);
amdgpu_ring_commit(ring); amdgpu_ring_commit(ring);
......
...@@ -175,7 +175,7 @@ static void uvd_v7_0_enc_ring_set_wptr(struct amdgpu_ring *ring) ...@@ -175,7 +175,7 @@ static void uvd_v7_0_enc_ring_set_wptr(struct amdgpu_ring *ring)
static int uvd_v7_0_enc_ring_test_ring(struct amdgpu_ring *ring) static int uvd_v7_0_enc_ring_test_ring(struct amdgpu_ring *ring)
{ {
struct amdgpu_device *adev = ring->adev; struct amdgpu_device *adev = ring->adev;
uint32_t rptr = amdgpu_ring_get_rptr(ring); uint32_t rptr;
unsigned i; unsigned i;
int r; int r;
...@@ -185,6 +185,9 @@ static int uvd_v7_0_enc_ring_test_ring(struct amdgpu_ring *ring) ...@@ -185,6 +185,9 @@ static int uvd_v7_0_enc_ring_test_ring(struct amdgpu_ring *ring)
r = amdgpu_ring_alloc(ring, 16); r = amdgpu_ring_alloc(ring, 16);
if (r) if (r)
return r; return r;
rptr = amdgpu_ring_get_rptr(ring);
amdgpu_ring_write(ring, HEVC_ENC_CMD_END); amdgpu_ring_write(ring, HEVC_ENC_CMD_END);
amdgpu_ring_commit(ring); amdgpu_ring_commit(ring);
......
...@@ -1570,6 +1570,50 @@ static void connector_bad_edid(struct drm_connector *connector, ...@@ -1570,6 +1570,50 @@ static void connector_bad_edid(struct drm_connector *connector,
} }
} }
/* Get override or firmware EDID */
static struct edid *drm_get_override_edid(struct drm_connector *connector)
{
struct edid *override = NULL;
if (connector->override_edid)
override = drm_edid_duplicate(connector->edid_blob_ptr->data);
if (!override)
override = drm_load_edid_firmware(connector);
return IS_ERR(override) ? NULL : override;
}
/**
* drm_add_override_edid_modes - add modes from override/firmware EDID
* @connector: connector we're probing
*
* Add modes from the override/firmware EDID, if available. Only to be used from
* drm_helper_probe_single_connector_modes() as a fallback for when DDC probe
* failed during drm_get_edid() and caused the override/firmware EDID to be
* skipped.
*
* Return: The number of modes added or 0 if we couldn't find any.
*/
int drm_add_override_edid_modes(struct drm_connector *connector)
{
struct edid *override;
int num_modes = 0;
override = drm_get_override_edid(connector);
if (override) {
drm_connector_update_edid_property(connector, override);
num_modes = drm_add_edid_modes(connector, override);
kfree(override);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] adding %d modes via fallback override/firmware EDID\n",
connector->base.id, connector->name, num_modes);
}
return num_modes;
}
EXPORT_SYMBOL(drm_add_override_edid_modes);
/** /**
* drm_do_get_edid - get EDID data using a custom EDID block read function * drm_do_get_edid - get EDID data using a custom EDID block read function
* @connector: connector we're probing * @connector: connector we're probing
...@@ -1597,15 +1641,10 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, ...@@ -1597,15 +1641,10 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
{ {
int i, j = 0, valid_extensions = 0; int i, j = 0, valid_extensions = 0;
u8 *edid, *new; u8 *edid, *new;
struct edid *override = NULL; struct edid *override;
if (connector->override_edid)
override = drm_edid_duplicate(connector->edid_blob_ptr->data);
if (!override)
override = drm_load_edid_firmware(connector);
if (!IS_ERR_OR_NULL(override)) override = drm_get_override_edid(connector);
if (override)
return override; return override;
if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
......
...@@ -255,7 +255,8 @@ static void *drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem) ...@@ -255,7 +255,8 @@ static void *drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
if (obj->import_attach) if (obj->import_attach)
shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf); shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
else else
shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, PAGE_KERNEL); shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT,
VM_MAP, pgprot_writecombine(PAGE_KERNEL));
if (!shmem->vaddr) { if (!shmem->vaddr) {
DRM_DEBUG_KMS("Failed to vmap pages\n"); DRM_DEBUG_KMS("Failed to vmap pages\n");
......
...@@ -42,6 +42,14 @@ static const struct drm_dmi_panel_orientation_data asus_t100ha = { ...@@ -42,6 +42,14 @@ static const struct drm_dmi_panel_orientation_data asus_t100ha = {
.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
}; };
static const struct drm_dmi_panel_orientation_data gpd_micropc = {
.width = 720,
.height = 1280,
.bios_dates = (const char * const []){ "04/26/2019",
NULL },
.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
};
static const struct drm_dmi_panel_orientation_data gpd_pocket = { static const struct drm_dmi_panel_orientation_data gpd_pocket = {
.width = 1200, .width = 1200,
.height = 1920, .height = 1920,
...@@ -50,6 +58,14 @@ static const struct drm_dmi_panel_orientation_data gpd_pocket = { ...@@ -50,6 +58,14 @@ static const struct drm_dmi_panel_orientation_data gpd_pocket = {
.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
}; };
static const struct drm_dmi_panel_orientation_data gpd_pocket2 = {
.width = 1200,
.height = 1920,
.bios_dates = (const char * const []){ "06/28/2018", "08/28/2018",
"12/07/2018", NULL },
.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
};
static const struct drm_dmi_panel_orientation_data gpd_win = { static const struct drm_dmi_panel_orientation_data gpd_win = {
.width = 720, .width = 720,
.height = 1280, .height = 1280,
...@@ -99,6 +115,14 @@ static const struct dmi_system_id orientation_data[] = { ...@@ -99,6 +115,14 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"),
}, },
.driver_data = (void *)&asus_t100ha, .driver_data = (void *)&asus_t100ha,
}, { /* GPD MicroPC (generic strings, also match on bios date) */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
},
.driver_data = (void *)&gpd_micropc,
}, { /* }, { /*
* GPD Pocket, note that the the DMI data is less generic then * GPD Pocket, note that the the DMI data is less generic then
* it seems, devices with a board-vendor of "AMI Corporation" * it seems, devices with a board-vendor of "AMI Corporation"
...@@ -112,6 +136,14 @@ static const struct dmi_system_id orientation_data[] = { ...@@ -112,6 +136,14 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
}, },
.driver_data = (void *)&gpd_pocket, .driver_data = (void *)&gpd_pocket,
}, { /* GPD Pocket 2 (generic strings, also match on bios date) */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
},
.driver_data = (void *)&gpd_pocket2,
}, { /* GPD Win (same note on DMI match as GPD Pocket) */ }, { /* GPD Win (same note on DMI match as GPD Pocket) */
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
......
...@@ -479,6 +479,13 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -479,6 +479,13 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
count = (*connector_funcs->get_modes)(connector); count = (*connector_funcs->get_modes)(connector);
/*
* Fallback for when DDC probe failed in drm_get_edid() and thus skipped
* override/firmware EDID.
*/
if (count == 0 && connector->status == connector_status_connected)
count = drm_add_override_edid_modes(connector);
if (count == 0 && connector->status == connector_status_connected) if (count == 0 && connector->status == connector_status_connected)
count = drm_add_modes_noedid(connector, 1024, 768); count = drm_add_modes_noedid(connector, 1024, 768);
count += drm_helper_probe_add_cmdline_mode(connector); count += drm_helper_probe_add_cmdline_mode(connector);
......
...@@ -3005,6 +3005,7 @@ static bool gen8_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) ...@@ -3005,6 +3005,7 @@ static bool gen8_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
static bool gen10_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) static bool gen10_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
{ {
return gen8_is_valid_mux_addr(dev_priv, addr) || return gen8_is_valid_mux_addr(dev_priv, addr) ||
addr == i915_mmio_reg_offset(GEN10_NOA_WRITE_HIGH) ||
(addr >= i915_mmio_reg_offset(OA_PERFCNT3_LO) && (addr >= i915_mmio_reg_offset(OA_PERFCNT3_LO) &&
addr <= i915_mmio_reg_offset(OA_PERFCNT4_HI)); addr <= i915_mmio_reg_offset(OA_PERFCNT4_HI));
} }
......
...@@ -1062,6 +1062,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) ...@@ -1062,6 +1062,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define NOA_DATA _MMIO(0x986C) #define NOA_DATA _MMIO(0x986C)
#define NOA_WRITE _MMIO(0x9888) #define NOA_WRITE _MMIO(0x9888)
#define GEN10_NOA_WRITE_HIGH _MMIO(0x9884)
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068 #define _GEN7_PIPEA_DE_LOAD_SL 0x70068
#define _GEN7_PIPEB_DE_LOAD_SL 0x71068 #define _GEN7_PIPEB_DE_LOAD_SL 0x71068
......
...@@ -303,10 +303,17 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv, ...@@ -303,10 +303,17 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
u32 dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes; u32 dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
u32 i; u32 i;
u32 *dmc_payload; u32 *dmc_payload;
size_t fsize;
if (!fw) if (!fw)
return NULL; return NULL;
fsize = sizeof(struct intel_css_header) +
sizeof(struct intel_package_header) +
sizeof(struct intel_dmc_header);
if (fsize > fw->size)
goto error_truncated;
/* Extract CSS Header information*/ /* Extract CSS Header information*/
css_header = (struct intel_css_header *)fw->data; css_header = (struct intel_css_header *)fw->data;
if (sizeof(struct intel_css_header) != if (sizeof(struct intel_css_header) !=
...@@ -366,6 +373,9 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv, ...@@ -366,6 +373,9 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
/* Convert dmc_offset into number of bytes. By default it is in dwords*/ /* Convert dmc_offset into number of bytes. By default it is in dwords*/
dmc_offset *= 4; dmc_offset *= 4;
readcount += dmc_offset; readcount += dmc_offset;
fsize += dmc_offset;
if (fsize > fw->size)
goto error_truncated;
/* Extract dmc_header information. */ /* Extract dmc_header information. */
dmc_header = (struct intel_dmc_header *)&fw->data[readcount]; dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
...@@ -397,6 +407,10 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv, ...@@ -397,6 +407,10 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */ /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
nbytes = dmc_header->fw_size * 4; nbytes = dmc_header->fw_size * 4;
fsize += nbytes;
if (fsize > fw->size)
goto error_truncated;
if (nbytes > csr->max_fw_size) { if (nbytes > csr->max_fw_size) {
DRM_ERROR("DMC FW too big (%u bytes)\n", nbytes); DRM_ERROR("DMC FW too big (%u bytes)\n", nbytes);
return NULL; return NULL;
...@@ -410,6 +424,10 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv, ...@@ -410,6 +424,10 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
} }
return memcpy(dmc_payload, &fw->data[readcount], nbytes); return memcpy(dmc_payload, &fw->data[readcount], nbytes);
error_truncated:
DRM_ERROR("Truncated DMC firmware, rejecting.\n");
return NULL;
} }
static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv) static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
......
...@@ -2432,10 +2432,14 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) ...@@ -2432,10 +2432,14 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)
* main surface. * main surface.
*/ */
static const struct drm_format_info ccs_formats[] = { static const struct drm_format_info ccs_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
}; };
static const struct drm_format_info * static const struct drm_format_info *
...@@ -11942,7 +11946,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, ...@@ -11942,7 +11946,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
return 0; return 0;
} }
static bool intel_fuzzy_clock_check(int clock1, int clock2) bool intel_fuzzy_clock_check(int clock1, int clock2)
{ {
int diff; int diff;
......
...@@ -1742,6 +1742,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, ...@@ -1742,6 +1742,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
const struct dpll *dpll); const struct dpll *dpll);
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe); void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
int lpt_get_iclkip(struct drm_i915_private *dev_priv); int lpt_get_iclkip(struct drm_i915_private *dev_priv);
bool intel_fuzzy_clock_check(int clock1, int clock2);
/* modesetting asserts */ /* modesetting asserts */
void assert_panel_unlocked(struct drm_i915_private *dev_priv, void assert_panel_unlocked(struct drm_i915_private *dev_priv,
......
...@@ -853,6 +853,17 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) ...@@ -853,6 +853,17 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
if (mipi_config->target_burst_mode_freq) { if (mipi_config->target_burst_mode_freq) {
u32 bitrate = intel_dsi_bitrate(intel_dsi); u32 bitrate = intel_dsi_bitrate(intel_dsi);
/*
* Sometimes the VBT contains a slightly lower clock,
* then the bitrate we have calculated, in this case
* just replace it with the calculated bitrate.
*/
if (mipi_config->target_burst_mode_freq < bitrate &&
intel_fuzzy_clock_check(
mipi_config->target_burst_mode_freq,
bitrate))
mipi_config->target_burst_mode_freq = bitrate;
if (mipi_config->target_burst_mode_freq < bitrate) { if (mipi_config->target_burst_mode_freq < bitrate) {
DRM_ERROR("Burst mode freq is less than computed\n"); DRM_ERROR("Burst mode freq is less than computed\n");
return false; return false;
......
...@@ -916,6 +916,13 @@ static bool intel_sdvo_set_colorimetry(struct intel_sdvo *intel_sdvo, ...@@ -916,6 +916,13 @@ static bool intel_sdvo_set_colorimetry(struct intel_sdvo *intel_sdvo,
return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1); return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
} }
static bool intel_sdvo_set_audio_state(struct intel_sdvo *intel_sdvo,
u8 audio_state)
{
return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_AUDIO_STAT,
&audio_state, 1);
}
#if 0 #if 0
static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
{ {
...@@ -1487,11 +1494,6 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, ...@@ -1487,11 +1494,6 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
else else
sdvox |= SDVO_PIPE_SEL(crtc->pipe); sdvox |= SDVO_PIPE_SEL(crtc->pipe);
if (crtc_state->has_audio) {
WARN_ON_ONCE(INTEL_GEN(dev_priv) < 4);
sdvox |= SDVO_AUDIO_ENABLE;
}
if (INTEL_GEN(dev_priv) >= 4) { if (INTEL_GEN(dev_priv) >= 4) {
/* done in crtc_mode_set as the dpll_md reg must be written early */ /* done in crtc_mode_set as the dpll_md reg must be written early */
} else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
...@@ -1635,8 +1637,13 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, ...@@ -1635,8 +1637,13 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
if (sdvox & HDMI_COLOR_RANGE_16_235) if (sdvox & HDMI_COLOR_RANGE_16_235)
pipe_config->limited_color_range = true; pipe_config->limited_color_range = true;
if (sdvox & SDVO_AUDIO_ENABLE) if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT,
pipe_config->has_audio = true; &val, 1)) {
u8 mask = SDVO_AUDIO_ELD_VALID | SDVO_AUDIO_PRESENCE_DETECT;
if ((val & mask) == mask)
pipe_config->has_audio = true;
}
if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE,
&val, 1)) { &val, 1)) {
...@@ -1647,6 +1654,32 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, ...@@ -1647,6 +1654,32 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
intel_sdvo_get_avi_infoframe(intel_sdvo, pipe_config); intel_sdvo_get_avi_infoframe(intel_sdvo, pipe_config);
} }
static void intel_sdvo_disable_audio(struct intel_sdvo *intel_sdvo)
{
intel_sdvo_set_audio_state(intel_sdvo, 0);
}
static void intel_sdvo_enable_audio(struct intel_sdvo *intel_sdvo,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
const struct drm_display_mode *adjusted_mode =
&crtc_state->base.adjusted_mode;
struct drm_connector *connector = conn_state->connector;
u8 *eld = connector->eld;
eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
intel_sdvo_set_audio_state(intel_sdvo, 0);
intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_ELD,
SDVO_HBUF_TX_DISABLED,
eld, drm_eld_size(eld));
intel_sdvo_set_audio_state(intel_sdvo, SDVO_AUDIO_ELD_VALID |
SDVO_AUDIO_PRESENCE_DETECT);
}
static void intel_disable_sdvo(struct intel_encoder *encoder, static void intel_disable_sdvo(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *conn_state) const struct drm_connector_state *conn_state)
...@@ -1656,6 +1689,9 @@ static void intel_disable_sdvo(struct intel_encoder *encoder, ...@@ -1656,6 +1689,9 @@ static void intel_disable_sdvo(struct intel_encoder *encoder,
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
u32 temp; u32 temp;
if (old_crtc_state->has_audio)
intel_sdvo_disable_audio(intel_sdvo);
intel_sdvo_set_active_outputs(intel_sdvo, 0); intel_sdvo_set_active_outputs(intel_sdvo, 0);
if (0) if (0)
intel_sdvo_set_encoder_power_state(intel_sdvo, intel_sdvo_set_encoder_power_state(intel_sdvo,
...@@ -1741,6 +1777,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder, ...@@ -1741,6 +1777,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder,
intel_sdvo_set_encoder_power_state(intel_sdvo, intel_sdvo_set_encoder_power_state(intel_sdvo,
DRM_MODE_DPMS_ON); DRM_MODE_DPMS_ON);
intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output); intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
if (pipe_config->has_audio)
intel_sdvo_enable_audio(intel_sdvo, pipe_config, conn_state);
} }
static enum drm_mode_status static enum drm_mode_status
...@@ -2603,7 +2642,6 @@ static bool ...@@ -2603,7 +2642,6 @@ static bool
intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
{ {
struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_encoder *encoder = &intel_sdvo->base.base;
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
struct drm_connector *connector; struct drm_connector *connector;
struct intel_encoder *intel_encoder = to_intel_encoder(encoder); struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
...@@ -2640,9 +2678,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) ...@@ -2640,9 +2678,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
encoder->encoder_type = DRM_MODE_ENCODER_TMDS; encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
connector->connector_type = DRM_MODE_CONNECTOR_DVID; connector->connector_type = DRM_MODE_CONNECTOR_DVID;
/* gen3 doesn't do the hdmi bits in the SDVO register */ if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
if (INTEL_GEN(dev_priv) >= 4 &&
intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
intel_sdvo_connector->is_hdmi = true; intel_sdvo_connector->is_hdmi = true;
} }
......
...@@ -707,6 +707,9 @@ struct intel_sdvo_enhancements_arg { ...@@ -707,6 +707,9 @@ struct intel_sdvo_enhancements_arg {
#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90 #define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90
#define SDVO_CMD_SET_AUDIO_STAT 0x91 #define SDVO_CMD_SET_AUDIO_STAT 0x91
#define SDVO_CMD_GET_AUDIO_STAT 0x92 #define SDVO_CMD_GET_AUDIO_STAT 0x92
#define SDVO_AUDIO_ELD_VALID (1 << 0)
#define SDVO_AUDIO_PRESENCE_DETECT (1 << 1)
#define SDVO_AUDIO_CP_READY (1 << 2)
#define SDVO_CMD_SET_HBUF_INDEX 0x93 #define SDVO_CMD_SET_HBUF_INDEX 0x93
#define SDVO_HBUF_INDEX_ELD 0 #define SDVO_HBUF_INDEX_ELD 0
#define SDVO_HBUF_INDEX_AVI_IF 1 #define SDVO_HBUF_INDEX_AVI_IF 1
......
...@@ -90,10 +90,6 @@ static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc) ...@@ -90,10 +90,6 @@ static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
static void mtk_drm_crtc_destroy(struct drm_crtc *crtc) static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
{ {
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
int i;
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
clk_unprepare(mtk_crtc->ddp_comp[i]->clk);
mtk_disp_mutex_put(mtk_crtc->mutex); mtk_disp_mutex_put(mtk_crtc->mutex);
...@@ -186,7 +182,7 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc) ...@@ -186,7 +182,7 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
DRM_DEBUG_DRIVER("%s\n", __func__); DRM_DEBUG_DRIVER("%s\n", __func__);
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
ret = clk_enable(mtk_crtc->ddp_comp[i]->clk); ret = clk_prepare_enable(mtk_crtc->ddp_comp[i]->clk);
if (ret) { if (ret) {
DRM_ERROR("Failed to enable clock %d: %d\n", i, ret); DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
goto err; goto err;
...@@ -196,7 +192,7 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc) ...@@ -196,7 +192,7 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
return 0; return 0;
err: err:
while (--i >= 0) while (--i >= 0)
clk_disable(mtk_crtc->ddp_comp[i]->clk); clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
return ret; return ret;
} }
...@@ -206,7 +202,7 @@ static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc) ...@@ -206,7 +202,7 @@ static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
DRM_DEBUG_DRIVER("%s\n", __func__); DRM_DEBUG_DRIVER("%s\n", __func__);
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
clk_disable(mtk_crtc->ddp_comp[i]->clk); clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
} }
static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
...@@ -577,15 +573,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, ...@@ -577,15 +573,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
if (!comp) { if (!comp) {
dev_err(dev, "Component %pOF not initialized\n", node); dev_err(dev, "Component %pOF not initialized\n", node);
ret = -ENODEV; ret = -ENODEV;
goto unprepare; return ret;
}
ret = clk_prepare(comp->clk);
if (ret) {
dev_err(dev,
"Failed to prepare clock for component %pOF: %d\n",
node, ret);
goto unprepare;
} }
mtk_crtc->ddp_comp[i] = comp; mtk_crtc->ddp_comp[i] = comp;
...@@ -603,23 +591,17 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, ...@@ -603,23 +591,17 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
ret = mtk_plane_init(drm_dev, &mtk_crtc->planes[zpos], ret = mtk_plane_init(drm_dev, &mtk_crtc->planes[zpos],
BIT(pipe), type); BIT(pipe), type);
if (ret) if (ret)
goto unprepare; return ret;
} }
ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0], ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0],
mtk_crtc->layer_nr > 1 ? &mtk_crtc->planes[1] : mtk_crtc->layer_nr > 1 ? &mtk_crtc->planes[1] :
NULL, pipe); NULL, pipe);
if (ret < 0) if (ret < 0)
goto unprepare; return ret;
drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE); drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE);
drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE); drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE);
priv->num_pipes++; priv->num_pipes++;
return 0; return 0;
unprepare:
while (--i >= 0)
clk_unprepare(mtk_crtc->ddp_comp[i]->clk);
return ret;
} }
...@@ -303,6 +303,7 @@ static int mtk_drm_kms_init(struct drm_device *drm) ...@@ -303,6 +303,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
static void mtk_drm_kms_deinit(struct drm_device *drm) static void mtk_drm_kms_deinit(struct drm_device *drm)
{ {
drm_kms_helper_poll_fini(drm); drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm);
component_unbind_all(drm->dev, drm); component_unbind_all(drm->dev, drm);
drm_mode_config_cleanup(drm); drm_mode_config_cleanup(drm);
...@@ -389,7 +390,9 @@ static void mtk_drm_unbind(struct device *dev) ...@@ -389,7 +390,9 @@ static void mtk_drm_unbind(struct device *dev)
struct mtk_drm_private *private = dev_get_drvdata(dev); struct mtk_drm_private *private = dev_get_drvdata(dev);
drm_dev_unregister(private->drm); drm_dev_unregister(private->drm);
mtk_drm_kms_deinit(private->drm);
drm_dev_put(private->drm); drm_dev_put(private->drm);
private->num_pipes = 0;
private->drm = NULL; private->drm = NULL;
} }
...@@ -560,13 +563,8 @@ static int mtk_drm_probe(struct platform_device *pdev) ...@@ -560,13 +563,8 @@ static int mtk_drm_probe(struct platform_device *pdev)
static int mtk_drm_remove(struct platform_device *pdev) static int mtk_drm_remove(struct platform_device *pdev)
{ {
struct mtk_drm_private *private = platform_get_drvdata(pdev); struct mtk_drm_private *private = platform_get_drvdata(pdev);
struct drm_device *drm = private->drm;
int i; int i;
drm_dev_unregister(drm);
mtk_drm_kms_deinit(drm);
drm_dev_put(drm);
component_master_del(&pdev->dev, &mtk_drm_ops); component_master_del(&pdev->dev, &mtk_drm_ops);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
of_node_put(private->mutex_node); of_node_put(private->mutex_node);
......
...@@ -136,7 +136,6 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, ...@@ -136,7 +136,6 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj,
* VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap(). * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
*/ */
vma->vm_flags &= ~VM_PFNMAP; vma->vm_flags &= ~VM_PFNMAP;
vma->vm_pgoff = 0;
ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie, ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie,
mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs); mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs);
...@@ -168,6 +167,12 @@ int mtk_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -168,6 +167,12 @@ int mtk_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
obj = vma->vm_private_data; obj = vma->vm_private_data;
/*
* Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the
* whole buffer from the start.
*/
vma->vm_pgoff = 0;
return mtk_drm_gem_object_mmap(obj, vma); return mtk_drm_gem_object_mmap(obj, vma);
} }
......
...@@ -622,6 +622,15 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi) ...@@ -622,6 +622,15 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
if (--dsi->refcount != 0) if (--dsi->refcount != 0)
return; return;
/*
* mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since
* mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(),
* which needs irq for vblank, and mtk_dsi_stop() will disable irq.
* mtk_dsi_start() needs to be called in mtk_output_dsi_enable(),
* after dsi is fully set.
*/
mtk_dsi_stop(dsi);
if (!mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500)) { if (!mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500)) {
if (dsi->panel) { if (dsi->panel) {
if (drm_panel_unprepare(dsi->panel)) { if (drm_panel_unprepare(dsi->panel)) {
...@@ -688,7 +697,6 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi) ...@@ -688,7 +697,6 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi)
} }
} }
mtk_dsi_stop(dsi);
mtk_dsi_poweroff(dsi); mtk_dsi_poweroff(dsi);
dsi->enabled = false; dsi->enabled = false;
...@@ -836,6 +844,8 @@ static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi) ...@@ -836,6 +844,8 @@ static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi)
/* Skip connector cleanup if creation was delegated to the bridge */ /* Skip connector cleanup if creation was delegated to the bridge */
if (dsi->conn.dev) if (dsi->conn.dev)
drm_connector_cleanup(&dsi->conn); drm_connector_cleanup(&dsi->conn);
if (dsi->panel)
drm_panel_detach(dsi->panel);
} }
static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp) static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp)
......
...@@ -107,8 +107,6 @@ static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -107,8 +107,6 @@ static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
priv->io_base + _REG(VPP_OUT_H_V_SIZE)); priv->io_base + _REG(VPP_OUT_H_V_SIZE));
drm_crtc_vblank_on(crtc); drm_crtc_vblank_on(crtc);
priv->viu.osd1_enabled = true;
} }
static void meson_crtc_atomic_enable(struct drm_crtc *crtc, static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
...@@ -137,8 +135,6 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -137,8 +135,6 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
priv->io_base + _REG(VPP_MISC)); priv->io_base + _REG(VPP_MISC));
drm_crtc_vblank_on(crtc); drm_crtc_vblank_on(crtc);
priv->viu.osd1_enabled = true;
} }
static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc, static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
...@@ -256,6 +252,8 @@ static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv) ...@@ -256,6 +252,8 @@ static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
writel_relaxed(priv->viu.osb_blend1_size, writel_relaxed(priv->viu.osb_blend1_size,
priv->io_base + priv->io_base +
_REG(VIU_OSD_BLEND_BLEND1_SIZE)); _REG(VIU_OSD_BLEND_BLEND1_SIZE));
writel_bits_relaxed(3 << 8, 3 << 8,
priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
} }
static void meson_crtc_enable_vd1(struct meson_drm *priv) static void meson_crtc_enable_vd1(struct meson_drm *priv)
......
...@@ -305,6 +305,8 @@ static void meson_plane_atomic_update(struct drm_plane *plane, ...@@ -305,6 +305,8 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
meson_plane->enabled = true; meson_plane->enabled = true;
} }
priv->viu.osd1_enabled = true;
spin_unlock_irqrestore(&priv->drm->event_lock, flags); spin_unlock_irqrestore(&priv->drm->event_lock, flags);
} }
...@@ -316,14 +318,14 @@ static void meson_plane_atomic_disable(struct drm_plane *plane, ...@@ -316,14 +318,14 @@ static void meson_plane_atomic_disable(struct drm_plane *plane,
/* Disable OSD1 */ /* Disable OSD1 */
if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
writel_bits_relaxed(BIT(0) | BIT(21), 0, writel_bits_relaxed(3 << 8, 0,
priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
else else
writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0, writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
priv->io_base + _REG(VPP_MISC)); priv->io_base + _REG(VPP_MISC));
meson_plane->enabled = false; meson_plane->enabled = false;
priv->viu.osd1_enabled = false;
} }
static const struct drm_plane_helper_funcs meson_plane_helper_funcs = { static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
......
...@@ -503,8 +503,17 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m, ...@@ -503,8 +503,17 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
/* G12A HDMI PLL Needs specific parameters for 5.4GHz */ /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
if (m >= 0xf7) { if (m >= 0xf7) {
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0xea68dc00); if (frac < 0x10000) {
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290); regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
0x6a685c00);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
0x11551293);
} else {
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
0xea68dc00);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
0x65771290);
}
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000); regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000); regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
} else { } else {
......
...@@ -405,8 +405,7 @@ void meson_viu_init(struct meson_drm *priv) ...@@ -405,8 +405,7 @@ void meson_viu_init(struct meson_drm *priv)
0 << 16 | 0 << 16 |
1, 1,
priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
writel_relaxed(3 << 8 | writel_relaxed(1 << 20,
1 << 20,
priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
writel_relaxed(1 << 20, writel_relaxed(1 << 20,
priv->io_base + _REG(OSD2_BLEND_SRC_CTRL)); priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
......
...@@ -10,6 +10,7 @@ config DRM_PANFROST ...@@ -10,6 +10,7 @@ config DRM_PANFROST
select IOMMU_IO_PGTABLE_LPAE select IOMMU_IO_PGTABLE_LPAE
select DRM_GEM_SHMEM_HELPER select DRM_GEM_SHMEM_HELPER
select PM_DEVFREQ select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
help help
DRM driver for ARM Mali Midgard (T6xx, T7xx, T8xx) and DRM driver for ARM Mali Midgard (T6xx, T7xx, T8xx) and
Bifrost (G3x, G5x, G7x) GPUs. Bifrost (G3x, G5x, G7x) GPUs.
...@@ -140,7 +140,9 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) ...@@ -140,7 +140,9 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
return 0; return 0;
ret = dev_pm_opp_of_add_table(&pfdev->pdev->dev); ret = dev_pm_opp_of_add_table(&pfdev->pdev->dev);
if (ret) if (ret == -ENODEV) /* Optional, continue without devfreq */
return 0;
else if (ret)
return ret; return ret;
panfrost_devfreq_reset(pfdev); panfrost_devfreq_reset(pfdev);
...@@ -170,6 +172,9 @@ void panfrost_devfreq_resume(struct panfrost_device *pfdev) ...@@ -170,6 +172,9 @@ void panfrost_devfreq_resume(struct panfrost_device *pfdev)
{ {
int i; int i;
if (!pfdev->devfreq.devfreq)
return;
panfrost_devfreq_reset(pfdev); panfrost_devfreq_reset(pfdev);
for (i = 0; i < NUM_JOB_SLOTS; i++) for (i = 0; i < NUM_JOB_SLOTS; i++)
pfdev->devfreq.slot[i].busy = false; pfdev->devfreq.slot[i].busy = false;
...@@ -179,6 +184,9 @@ void panfrost_devfreq_resume(struct panfrost_device *pfdev) ...@@ -179,6 +184,9 @@ void panfrost_devfreq_resume(struct panfrost_device *pfdev)
void panfrost_devfreq_suspend(struct panfrost_device *pfdev) void panfrost_devfreq_suspend(struct panfrost_device *pfdev)
{ {
if (!pfdev->devfreq.devfreq)
return;
devfreq_suspend_device(pfdev->devfreq.devfreq); devfreq_suspend_device(pfdev->devfreq.devfreq);
} }
...@@ -188,6 +196,9 @@ static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev, i ...@@ -188,6 +196,9 @@ static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev, i
ktime_t now; ktime_t now;
ktime_t last; ktime_t last;
if (!pfdev->devfreq.devfreq)
return;
now = ktime_get(); now = ktime_get();
last = pfdev->devfreq.slot[slot].time_last_update; last = pfdev->devfreq.slot[slot].time_last_update;
......
...@@ -471,6 +471,7 @@ struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, ...@@ -471,6 +471,7 @@ struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
struct edid *drm_edid_duplicate(const struct edid *edid); struct edid *drm_edid_duplicate(const struct edid *edid);
int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
int drm_add_override_edid_modes(struct drm_connector *connector);
u8 drm_match_cea_mode(const struct drm_display_mode *to_match); u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code); enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment