summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vc4
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vc4')
-rw-r--r--drivers/gpu/drm/vc4/Kconfig1
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock.c6
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock.h9
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock_plane.c44
-rw-r--r--drivers/gpu/drm/vc4/vc4_bo.c14
-rw-r--r--drivers/gpu/drm/vc4/vc4_dpi.c14
-rw-r--r--drivers/gpu/drm/vc4/vc4_dsi.c32
-rw-r--r--drivers/gpu/drm/vc4/vc4_gem.c11
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c688
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.h44
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi_phy.c6
-rw-r--r--drivers/gpu/drm/vc4/vc4_hvs.c4
-rw-r--r--drivers/gpu/drm/vc4/vc4_irq.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_perfmon.c7
-rw-r--r--drivers/gpu/drm/vc4/vc4_v3d.c24
-rw-r--r--drivers/gpu/drm/vc4/vc4_validate.c8
-rw-r--r--drivers/gpu/drm/vc4/vc4_vec.c41
17 files changed, 223 insertions, 732 deletions
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
index 91dcf8d174d6..269b5f26b2ea 100644
--- a/drivers/gpu/drm/vc4/Kconfig
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -10,6 +10,7 @@ config DRM_VC4
depends on COMMON_CLK
depends on PM
select DRM_DISPLAY_HDMI_HELPER
+ select DRM_DISPLAY_HDMI_STATE_HELPER
select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.c b/drivers/gpu/drm/vc4/tests/vc4_mock.c
index becb3dbaa548..0731a7d85d7a 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c
@@ -109,16 +109,14 @@ static const struct vc4_mock_desc vc5_mock =
static int __build_one_pipe(struct kunit *test, struct drm_device *drm,
const struct vc4_mock_pipe_desc *pipe)
{
- struct vc4_dummy_plane *dummy_plane;
struct drm_plane *plane;
struct vc4_dummy_crtc *dummy_crtc;
struct drm_crtc *crtc;
unsigned int i;
- dummy_plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
+ plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
- plane = &dummy_plane->plane.base;
dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc);
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h b/drivers/gpu/drm/vc4/tests/vc4_mock.h
index 2d0b339bd9f3..002b6218960c 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h
@@ -21,13 +21,8 @@ struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit *test,
return NULL;
}
-struct vc4_dummy_plane {
- struct vc4_plane plane;
-};
-
-struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
- struct drm_device *drm,
- enum drm_plane_type type);
+struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm,
+ enum drm_plane_type type);
struct vc4_dummy_crtc {
struct vc4_crtc crtc;
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
index 62b18f5f41db..14357db82238 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
@@ -1,47 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
-#include <drm/drm_atomic_state_helper.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_kunit_helpers.h>
#include <drm/drm_plane.h>
#include <kunit/test.h>
#include "vc4_mock.h"
-static const struct drm_plane_helper_funcs vc4_dummy_plane_helper_funcs = {
-};
-
-static const struct drm_plane_funcs vc4_dummy_plane_funcs = {
- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
- .reset = drm_atomic_helper_plane_reset,
-};
-
-static const uint32_t vc4_dummy_plane_formats[] = {
- DRM_FORMAT_XRGB8888,
-};
-
-struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
- struct drm_device *drm,
- enum drm_plane_type type)
+struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm,
+ enum drm_plane_type type)
{
- struct vc4_dummy_plane *dummy_plane;
struct drm_plane *plane;
- dummy_plane = drmm_universal_plane_alloc(drm,
- struct vc4_dummy_plane, plane.base,
- 0,
- &vc4_dummy_plane_funcs,
- vc4_dummy_plane_formats,
- ARRAY_SIZE(vc4_dummy_plane_formats),
- NULL,
- DRM_PLANE_TYPE_PRIMARY,
- NULL);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
+ KUNIT_ASSERT_EQ(test, type, DRM_PLANE_TYPE_PRIMARY);
- plane = &dummy_plane->plane.base;
- drm_plane_helper_add(plane, &vc4_dummy_plane_helper_funcs);
+ plane = drm_kunit_helper_create_primary_plane(test, drm,
+ NULL,
+ NULL,
+ NULL, 0,
+ NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
- return dummy_plane;
+ return plane;
}
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index 86d629e45307..3f72be7490d5 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -469,7 +469,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
if (IS_ERR(dma_obj)) {
struct drm_printer p = drm_info_printer(vc4->base.dev);
- DRM_ERROR("Failed to allocate from GEM DMA helper:\n");
+ drm_err(dev, "Failed to allocate from GEM DMA helper:\n");
vc4_bo_stats_print(&p, vc4);
return ERR_PTR(-ENOMEM);
}
@@ -702,7 +702,7 @@ static struct dma_buf *vc4_prime_export(struct drm_gem_object *obj, int flags)
*/
ret = vc4_bo_inc_usecnt(bo);
if (ret) {
- DRM_ERROR("Failed to increment BO usecnt\n");
+ drm_err(obj->dev, "Failed to increment BO usecnt\n");
return ERR_PTR(ret);
}
@@ -1050,10 +1050,10 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused)
for (i = 0; i < vc4->num_labels; i++) {
if (vc4->bo_labels[i].num_allocated) {
- DRM_ERROR("Destroying BO cache with %d %s "
- "BOs still allocated\n",
- vc4->bo_labels[i].num_allocated,
- vc4->bo_labels[i].name);
+ drm_err(dev, "Destroying BO cache with %d %s "
+ "BOs still allocated\n",
+ vc4->bo_labels[i].num_allocated,
+ vc4->bo_labels[i].name);
}
if (is_user_label(i))
@@ -1083,7 +1083,7 @@ int vc4_label_bo_ioctl(struct drm_device *dev, void *data,
gem_obj = drm_gem_object_lookup(file_priv, args->handle);
if (!gem_obj) {
- DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+ drm_err(dev, "Failed to look up GEM BO %d\n", args->handle);
kfree(name);
return -ENOENT;
}
diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
index 39152e755a13..a382dc4654bd 100644
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -199,8 +199,8 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
DPI_FORMAT);
break;
default:
- DRM_ERROR("Unknown media bus format %d\n",
- bus_format);
+ drm_err(dev, "Unknown media bus format %d\n",
+ bus_format);
break;
}
}
@@ -236,11 +236,11 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
ret = clk_set_rate(dpi->pixel_clock, mode->clock * 1000);
if (ret)
- DRM_ERROR("Failed to set clock rate: %d\n", ret);
+ drm_err(dev, "Failed to set clock rate: %d\n", ret);
ret = clk_prepare_enable(dpi->pixel_clock);
if (ret)
- DRM_ERROR("Failed to set clock rate: %d\n", ret);
+ drm_err(dev, "Failed to set clock rate: %d\n", ret);
drm_dev_exit(idx);
}
@@ -339,7 +339,7 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
if (IS_ERR(dpi->core_clock)) {
ret = PTR_ERR(dpi->core_clock);
if (ret != -EPROBE_DEFER)
- DRM_ERROR("Failed to get core clock: %d\n", ret);
+ drm_err(drm, "Failed to get core clock: %d\n", ret);
return ret;
}
@@ -347,13 +347,13 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
if (IS_ERR(dpi->pixel_clock)) {
ret = PTR_ERR(dpi->pixel_clock);
if (ret != -EPROBE_DEFER)
- DRM_ERROR("Failed to get pixel clock: %d\n", ret);
+ drm_err(drm, "Failed to get pixel clock: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(dpi->core_clock);
if (ret) {
- DRM_ERROR("Failed to turn on core clock: %d\n", ret);
+ drm_err(drm, "Failed to turn on core clock: %d\n", ret);
return ret;
}
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index 46f6c4ce61c5..f5ccc1bf7a63 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -613,6 +613,7 @@ struct vc4_dsi {
static inline void
dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
{
+ struct drm_device *drm = dsi->bridge.dev;
struct dma_chan *chan = dsi->reg_dma_chan;
struct dma_async_tx_descriptor *tx;
dma_cookie_t cookie;
@@ -633,19 +634,19 @@ dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
dsi->reg_dma_paddr,
4, 0);
if (!tx) {
- DRM_ERROR("Failed to set up DMA register write\n");
+ drm_err(drm, "Failed to set up DMA register write\n");
return;
}
cookie = tx->tx_submit(tx);
ret = dma_submit_error(cookie);
if (ret) {
- DRM_ERROR("Failed to submit DMA: %d\n", ret);
+ drm_err(drm, "Failed to submit DMA: %d\n", ret);
return;
}
ret = dma_sync_wait(chan, cookie);
if (ret)
- DRM_ERROR("Failed to wait for DMA: %d\n", ret);
+ drm_err(drm, "Failed to wait for DMA: %d\n", ret);
}
#define DSI_READ(offset) \
@@ -893,7 +894,7 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
ret = pm_runtime_resume_and_get(dev);
if (ret) {
- DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port);
+ drm_err(bridge->dev, "Failed to runtime PM enable on DSI%d\n", dsi->variant->port);
return;
}
@@ -986,13 +987,14 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
ret = clk_prepare_enable(dsi->escape_clock);
if (ret) {
- DRM_ERROR("Failed to turn on DSI escape clock: %d\n", ret);
+ drm_err(bridge->dev, "Failed to turn on DSI escape clock: %d\n",
+ ret);
return;
}
ret = clk_prepare_enable(dsi->pll_phy_clock);
if (ret) {
- DRM_ERROR("Failed to turn on DSI PLL: %d\n", ret);
+ drm_err(bridge->dev, "Failed to turn on DSI PLL: %d\n", ret);
return;
}
@@ -1014,7 +1016,7 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
ret = clk_prepare_enable(dsi->pixel_clock);
if (ret) {
- DRM_ERROR("Failed to turn on DSI pixel clock: %d\n", ret);
+ drm_err(bridge->dev, "Failed to turn on DSI pixel clock: %d\n", ret);
return;
}
@@ -1172,6 +1174,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
struct vc4_dsi *dsi = host_to_dsi(host);
+ struct drm_device *drm = dsi->bridge.dev;
struct mipi_dsi_packet packet;
u32 pkth = 0, pktc = 0;
int i, ret;
@@ -1303,8 +1306,8 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
DSI_RXPKT1H_BC_PARAM);
if (rxlen != msg->rx_len) {
- DRM_ERROR("DSI returned %db, expecting %db\n",
- rxlen, (int)msg->rx_len);
+ drm_err(drm, "DSI returned %db, expecting %db\n",
+ rxlen, (int)msg->rx_len);
ret = -ENXIO;
goto reset_fifo_and_return;
}
@@ -1326,7 +1329,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
return ret;
reset_fifo_and_return:
- DRM_ERROR("DSI transfer failed, resetting: %d\n", ret);
+ drm_err(drm, "DSI transfer failed, resetting: %d\n", ret);
DSI_PORT_WRITE(TXPKT1C, DSI_PORT_READ(TXPKT1C) & ~DSI_TXPKT1C_CMD_EN);
udelay(1);
@@ -1468,7 +1471,8 @@ static void dsi_handle_error(struct vc4_dsi *dsi,
if (!(stat & bit))
return;
- DRM_ERROR("DSI%d: %s error\n", dsi->variant->port, type);
+ drm_err(dsi->bridge.dev, "DSI%d: %s error\n", dsi->variant->port,
+ type);
*ret = IRQ_HANDLED;
}
@@ -1687,7 +1691,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
&dsi->reg_dma_paddr,
GFP_KERNEL);
if (!dsi->reg_dma_mem) {
- DRM_ERROR("Failed to get DMA memory\n");
+ drm_err(drm, "Failed to get DMA memory\n");
return -ENOMEM;
}
@@ -1702,8 +1706,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
if (IS_ERR(dsi->reg_dma_chan)) {
ret = PTR_ERR(dsi->reg_dma_chan);
if (ret != -EPROBE_DEFER)
- DRM_ERROR("Failed to get DMA channel: %d\n",
- ret);
+ drm_err(drm, "Failed to get DMA channel: %d\n",
+ ret);
return ret;
}
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index 03648f954985..24fb1b57e1dd 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -832,8 +832,8 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
*/
temp = kvmalloc_array(temp_size, 1, GFP_KERNEL);
if (!temp) {
- DRM_ERROR("Failed to allocate storage for copying "
- "in bin/render CLs.\n");
+ drm_err(dev, "Failed to allocate storage for copying "
+ "in bin/render CLs.\n");
ret = -ENOMEM;
goto fail;
}
@@ -866,7 +866,7 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
bo = vc4_bo_create(dev, exec_size, true, VC4_BO_TYPE_BCL);
if (IS_ERR(bo)) {
- DRM_ERROR("Couldn't allocate BO for binning\n");
+ drm_err(dev, "Couldn't allocate BO for binning\n");
ret = PTR_ERR(bo);
goto fail;
}
@@ -1153,10 +1153,9 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
}
exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
- if (!exec) {
- DRM_ERROR("malloc failure on exec struct\n");
+ if (!exec)
return -ENOMEM;
- }
+
exec->dev = vc4;
ret = vc4_v3d_pm_get(vc4);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d30f8e8e8967..6611ab7c26a6 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -32,6 +32,7 @@
*/
#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
#include <drm/display/drm_scdc_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
@@ -110,25 +111,6 @@
#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000)
-static const char * const output_format_str[] = {
- [VC4_HDMI_OUTPUT_RGB] = "RGB",
- [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0",
- [VC4_HDMI_OUTPUT_YUV422] = "YUV 4:2:2",
- [VC4_HDMI_OUTPUT_YUV444] = "YUV 4:4:4",
-};
-
-static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt)
-{
- if (fmt >= ARRAY_SIZE(output_format_str))
- return "invalid";
-
- return output_format_str[fmt];
-}
-
-static unsigned long long
-vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
- unsigned int bpc, enum vc4_hdmi_output_format fmt);
-
static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi)
{
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
@@ -147,28 +129,13 @@ static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi)
static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode,
unsigned int bpc,
- enum vc4_hdmi_output_format fmt)
+ enum hdmi_colorspace fmt)
{
- unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
+ unsigned long long clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt);
return clock > HDMI_14_MAX_TMDS_CLK;
}
-static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state)
-{
- const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
- struct drm_display_info *display = &vc4_hdmi->connector.display_info;
-
- if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED)
- return false;
- else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL)
- return true;
-
- return !display->is_hdmi ||
- drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL;
-}
-
static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
{
struct drm_debugfs_entry *entry = m->private;
@@ -462,6 +429,7 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
{
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
enum drm_connector_status status = connector_status_disconnected;
+ int ret;
/*
* NOTE: This function should really take vc4_hdmi->mutex, but
@@ -474,7 +442,12 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
* the lock for now.
*/
- WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev));
+ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
+ if (ret) {
+ drm_err_once(connector->dev, "Failed to retain HDMI power domain: %d\n",
+ ret);
+ return connector_status_unknown;
+ }
if (vc4_hdmi->hpd_gpio) {
if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio))
@@ -524,7 +497,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
const struct drm_display_mode *mode;
list_for_each_entry(mode, &connector->probed_modes, head) {
- if (vc4_hdmi_mode_needs_scrambling(mode, 8, VC4_HDMI_OUTPUT_RGB)) {
+ if (vc4_hdmi_mode_needs_scrambling(mode, 8, HDMI_COLORSPACE_RGB)) {
drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz.");
drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60.");
}
@@ -539,12 +512,8 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
{
struct drm_connector_state *old_state =
drm_atomic_get_old_connector_state(state, connector);
- struct vc4_hdmi_connector_state *old_vc4_state =
- conn_state_to_vc4_hdmi_conn_state(old_state);
struct drm_connector_state *new_state =
drm_atomic_get_new_connector_state(state, connector);
- struct vc4_hdmi_connector_state *new_vc4_state =
- conn_state_to_vc4_hdmi_conn_state(new_state);
struct drm_crtc *crtc = new_state->crtc;
if (!crtc)
@@ -576,9 +545,7 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
return ret;
}
- if (old_state->colorspace != new_state->colorspace ||
- old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb ||
- !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
+ if (old_state->colorspace != new_state->colorspace) {
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
@@ -588,112 +555,21 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
crtc_state->mode_changed = true;
}
- return 0;
-}
-
-static int vc4_hdmi_connector_get_property(struct drm_connector *connector,
- const struct drm_connector_state *state,
- struct drm_property *property,
- uint64_t *val)
-{
- struct drm_device *drm = connector->dev;
- struct vc4_hdmi *vc4_hdmi =
- connector_to_vc4_hdmi(connector);
- const struct vc4_hdmi_connector_state *vc4_conn_state =
- conn_state_to_vc4_hdmi_conn_state(state);
-
- if (property == vc4_hdmi->broadcast_rgb_property) {
- *val = vc4_conn_state->broadcast_rgb;
- } else {
- drm_dbg(drm, "Unknown property [PROP:%d:%s]\n",
- property->base.id, property->name);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vc4_hdmi_connector_set_property(struct drm_connector *connector,
- struct drm_connector_state *state,
- struct drm_property *property,
- uint64_t val)
-{
- struct drm_device *drm = connector->dev;
- struct vc4_hdmi *vc4_hdmi =
- connector_to_vc4_hdmi(connector);
- struct vc4_hdmi_connector_state *vc4_conn_state =
- conn_state_to_vc4_hdmi_conn_state(state);
-
- if (property == vc4_hdmi->broadcast_rgb_property) {
- vc4_conn_state->broadcast_rgb = val;
- return 0;
- }
-
- drm_dbg(drm, "Unknown property [PROP:%d:%s]\n",
- property->base.id, property->name);
- return -EINVAL;
+ return drm_atomic_helper_connector_hdmi_check(connector, state);
}
static void vc4_hdmi_connector_reset(struct drm_connector *connector)
{
- struct vc4_hdmi_connector_state *old_state =
- conn_state_to_vc4_hdmi_conn_state(connector->state);
- struct vc4_hdmi_connector_state *new_state =
- kzalloc(sizeof(*new_state), GFP_KERNEL);
-
- if (connector->state)
- __drm_atomic_helper_connector_destroy_state(connector->state);
-
- kfree(old_state);
- __drm_atomic_helper_connector_reset(connector, &new_state->base);
-
- if (!new_state)
- return;
-
- new_state->base.max_bpc = 8;
- new_state->base.max_requested_bpc = 8;
- new_state->output_format = VC4_HDMI_OUTPUT_RGB;
- new_state->broadcast_rgb = VC4_HDMI_BROADCAST_RGB_AUTO;
+ drm_atomic_helper_connector_reset(connector);
+ __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
drm_atomic_helper_connector_tv_margins_reset(connector);
}
-static struct drm_connector_state *
-vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
-{
- struct drm_connector_state *conn_state = connector->state;
- struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
- struct vc4_hdmi_connector_state *new_state;
-
- new_state = kzalloc(sizeof(*new_state), GFP_KERNEL);
- if (!new_state)
- return NULL;
-
- new_state->tmds_char_rate = vc4_state->tmds_char_rate;
- new_state->output_bpc = vc4_state->output_bpc;
- new_state->output_format = vc4_state->output_format;
- new_state->broadcast_rgb = vc4_state->broadcast_rgb;
- __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
-
- return &new_state->base;
-}
-
-static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector,
- struct drm_connector_state *state)
-{
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
-
- __drm_atomic_helper_connector_destroy_state(state);
- kfree(vc4_state);
-}
-
static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.reset = vc4_hdmi_connector_reset,
- .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
- .atomic_destroy_state = vc4_hdmi_connector_destroy_state,
- .atomic_get_property = vc4_hdmi_connector_get_property,
- .atomic_set_property = vc4_hdmi_connector_set_property,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = {
@@ -702,44 +578,29 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
.atomic_check = vc4_hdmi_connector_atomic_check,
};
-static const struct drm_prop_enum_list broadcast_rgb_names[] = {
- { VC4_HDMI_BROADCAST_RGB_AUTO, "Automatic" },
- { VC4_HDMI_BROADCAST_RGB_FULL, "Full" },
- { VC4_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" },
-};
-
-static void
-vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev,
- struct vc4_hdmi *vc4_hdmi)
-{
- struct drm_property *prop = vc4_hdmi->broadcast_rgb_property;
-
- if (!prop) {
- prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
- "Broadcast RGB",
- broadcast_rgb_names,
- ARRAY_SIZE(broadcast_rgb_names));
- if (!prop)
- return;
-
- vc4_hdmi->broadcast_rgb_property = prop;
- }
-
- drm_object_attach_property(&vc4_hdmi->connector.base, prop,
- VC4_HDMI_BROADCAST_RGB_AUTO);
-}
+static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs;
static int vc4_hdmi_connector_init(struct drm_device *dev,
struct vc4_hdmi *vc4_hdmi)
{
struct drm_connector *connector = &vc4_hdmi->connector;
struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
+ unsigned int max_bpc = 8;
int ret;
- ret = drmm_connector_init(dev, connector,
- &vc4_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA,
- vc4_hdmi->ddc);
+ if (vc4_hdmi->variant->supports_hdr)
+ max_bpc = 12;
+
+ ret = drmm_connector_hdmi_init(dev, connector,
+ "Broadcom", "Videocore",
+ &vc4_hdmi_connector_funcs,
+ &vc4_hdmi_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ vc4_hdmi->ddc,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ max_bpc);
if (ret)
return ret;
@@ -763,7 +624,6 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
drm_connector_attach_colorspace_property(connector);
drm_connector_attach_tv_margin_properties(connector);
- drm_connector_attach_max_bpc_property(connector, 8, 12);
connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT);
@@ -772,21 +632,19 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
connector->doublescan_allowed = 0;
connector->stereo_allowed = 1;
- if (vc4_hdmi->variant->supports_hdr)
- drm_connector_attach_hdr_output_metadata_property(connector);
-
- vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi);
+ ret = drm_connector_attach_broadcast_rgb_property(connector);
+ if (ret)
+ return ret;
drm_connector_attach_encoder(connector, encoder);
return 0;
}
-static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
+static int vc4_hdmi_stop_packet(struct vc4_hdmi *vc4_hdmi,
enum hdmi_infoframe_type type,
bool poll)
{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_device *drm = vc4_hdmi->connector.dev;
u32 packet_id = type - 0x80;
unsigned long flags;
@@ -810,12 +668,13 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
return ret;
}
-static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
- union hdmi_infoframe *frame)
+static int vc4_hdmi_write_infoframe(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *infoframe, size_t len)
{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_device *drm = vc4_hdmi->connector.dev;
- u32 packet_id = frame->any.type - 0x80;
+ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+ struct drm_device *drm = connector->dev;
+ u32 packet_id = type - 0x80;
const struct vc4_hdmi_register *ram_packet_start =
&vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
@@ -825,24 +684,27 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
ram_packet_start->reg);
uint8_t buffer[VC4_HDMI_PACKET_STRIDE] = {};
unsigned long flags;
- ssize_t len, i;
+ ssize_t i;
int ret;
int idx;
if (!drm_dev_enter(drm, &idx))
- return;
+ return 0;
+
+ if (len > sizeof(buffer)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(buffer, infoframe, len);
WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
VC4_HDMI_RAM_PACKET_ENABLE),
"Packet RAM has to be on to store the packet.");
- len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
- if (len < 0)
- goto out;
-
- ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true);
+ ret = vc4_hdmi_stop_packet(vc4_hdmi, type, true);
if (ret) {
- DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret);
+ drm_err(drm, "Failed to wait for infoframe to go idle: %d\n", ret);
goto out;
}
@@ -878,134 +740,11 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
BIT(packet_id)), 100);
if (ret)
- DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
+ drm_err(drm, "Failed to wait for infoframe to start: %d\n", ret);
out:
drm_dev_exit(idx);
-}
-
-static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
- enum vc4_hdmi_output_format fmt)
-{
- switch (fmt) {
- case VC4_HDMI_OUTPUT_RGB:
- frame->colorspace = HDMI_COLORSPACE_RGB;
- break;
-
- case VC4_HDMI_OUTPUT_YUV420:
- frame->colorspace = HDMI_COLORSPACE_YUV420;
- break;
-
- case VC4_HDMI_OUTPUT_YUV422:
- frame->colorspace = HDMI_COLORSPACE_YUV422;
- break;
-
- case VC4_HDMI_OUTPUT_YUV444:
- frame->colorspace = HDMI_COLORSPACE_YUV444;
- break;
-
- default:
- break;
- }
-}
-
-static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_connector *connector = &vc4_hdmi->connector;
- struct drm_connector_state *cstate = connector->state;
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(cstate);
- const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
- union hdmi_infoframe frame;
- int ret;
-
- lockdep_assert_held(&vc4_hdmi->mutex);
-
- ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
- connector, mode);
- if (ret < 0) {
- DRM_ERROR("couldn't fill AVI infoframe\n");
- return;
- }
-
- drm_hdmi_avi_infoframe_quant_range(&frame.avi,
- connector, mode,
- vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ?
- HDMI_QUANTIZATION_RANGE_FULL :
- HDMI_QUANTIZATION_RANGE_LIMITED);
- drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate);
- vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format);
- drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);
-
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
-{
- union hdmi_infoframe frame;
- int ret;
-
- ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore");
- if (ret < 0) {
- DRM_ERROR("couldn't fill SPD infoframe\n");
- return;
- }
-
- frame.spd.sdi = HDMI_SPD_SDI_PC;
-
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe;
- union hdmi_infoframe frame;
-
- memcpy(&frame.audio, audio, sizeof(*audio));
-
- if (vc4_hdmi->packet_ram_enabled)
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_hdr_infoframe(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_connector *connector = &vc4_hdmi->connector;
- struct drm_connector_state *conn_state = connector->state;
- union hdmi_infoframe frame;
-
- lockdep_assert_held(&vc4_hdmi->mutex);
-
- if (!vc4_hdmi->variant->supports_hdr)
- return;
-
- if (!conn_state->hdr_output_metadata)
- return;
-
- if (drm_hdmi_infoframe_set_hdr_metadata(&frame.drm, conn_state))
- return;
-
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-
- lockdep_assert_held(&vc4_hdmi->mutex);
-
- vc4_hdmi_set_avi_infoframe(encoder);
- vc4_hdmi_set_spd_infoframe(encoder);
- /*
- * If audio was streaming, then we need to reenabled the audio
- * infoframe here during encoder_enable.
- */
- if (vc4_hdmi->audio.streaming)
- vc4_hdmi_set_audio_infoframe(encoder);
-
- vc4_hdmi_set_hdr_infoframe(encoder);
+ return ret;
}
#define SCRAMBLING_POLLING_DELAY_MS 1000
@@ -1162,7 +901,7 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
if (ret < 0)
- DRM_ERROR("Failed to release power domain: %d\n", ret);
+ drm_err(drm, "Failed to release power domain: %d\n", ret);
drm_dev_exit(idx);
@@ -1174,8 +913,6 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
struct drm_connector_state *state,
const struct drm_display_mode *mode)
{
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
struct drm_device *drm = vc4_hdmi->connector.dev;
unsigned long flags;
u32 csc_ctl;
@@ -1189,7 +926,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
VC4_HD_CSC_CTL_ORDER);
- if (!vc4_hdmi_is_full_range(vc4_hdmi, vc4_state)) {
+ if (state->hdmi.is_limited_range) {
/* CEA VICs other than #1 requre limited range RGB
* output unless overridden by an AVI infoframe.
* Apply a colorspace conversion to squash 0-255 down
@@ -1412,9 +1149,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
const struct drm_display_mode *mode)
{
struct drm_device *drm = vc4_hdmi->connector.dev;
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
- unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ? 0 : 1;
+ unsigned int lim_range = state->hdmi.is_limited_range ? 1 : 0;
unsigned long flags;
const u16 (*csc)[4];
u32 if_cfg = 0;
@@ -1429,14 +1164,14 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
- switch (vc4_state->output_format) {
- case VC4_HDMI_OUTPUT_YUV444:
+ switch (state->hdmi.output_format) {
+ case HDMI_COLORSPACE_YUV444:
csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range);
vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc);
break;
- case VC4_HDMI_OUTPUT_YUV422:
+ case HDMI_COLORSPACE_YUV422:
csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range);
csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD,
@@ -1453,7 +1188,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc);
break;
- case VC4_HDMI_OUTPUT_RGB:
+ case HDMI_COLORSPACE_RGB:
if_xbar = 0x354021;
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]);
@@ -1542,8 +1277,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
const struct drm_display_mode *mode)
{
struct drm_device *drm = vc4_hdmi->connector.dev;
- const struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -1595,7 +1328,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
HDMI_WRITE(HDMI_VERTB0, vertb_even);
HDMI_WRITE(HDMI_VERTB1, vertb);
- switch (vc4_state->output_bpc) {
+ switch (state->hdmi.output_bpc) {
case 12:
gcp = 6;
break;
@@ -1612,7 +1345,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
* YCC422 is always 36-bit and not considered deep colour so
* doesn't signal in GCP.
*/
- if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) {
+ if (state->hdmi.output_format == HDMI_COLORSPACE_YUV422) {
gcp = 0;
}
@@ -1696,10 +1429,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
struct drm_connector *connector = &vc4_hdmi->connector;
struct drm_connector_state *conn_state =
drm_atomic_get_new_connector_state(state, connector);
- struct vc4_hdmi_connector_state *vc4_conn_state =
- conn_state_to_vc4_hdmi_conn_state(conn_state);
const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
- unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate;
+ unsigned long long tmds_char_rate = conn_state->hdmi.tmds_char_rate;
unsigned long bvb_rate, hsm_rate;
unsigned long flags;
int ret;
@@ -1712,7 +1443,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
if (ret < 0) {
- DRM_ERROR("Failed to retain power domain: %d\n", ret);
+ drm_err(drm, "Failed to retain power domain: %d\n", ret);
goto err_dev_exit;
}
@@ -1734,22 +1465,22 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
*/
hsm_rate = max_t(unsigned long,
HSM_MIN_CLOCK_FREQ,
- (tmds_char_rate / 100) * 101);
+ div_u64(tmds_char_rate, 100) * 101);
ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
if (ret) {
- DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
+ drm_err(drm, "Failed to set HSM clock rate: %d\n", ret);
goto err_put_runtime_pm;
}
ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate);
if (ret) {
- DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
+ drm_err(drm, "Failed to set pixel clock rate: %d\n", ret);
goto err_put_runtime_pm;
}
ret = clk_prepare_enable(vc4_hdmi->pixel_clock);
if (ret) {
- DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
+ drm_err(drm, "Failed to turn on pixel clock: %d\n", ret);
goto err_put_runtime_pm;
}
@@ -1765,18 +1496,18 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate);
if (ret) {
- DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret);
+ drm_err(drm, "Failed to set pixel bvb clock rate: %d\n", ret);
goto err_disable_pixel_clock;
}
ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
if (ret) {
- DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret);
+ drm_err(drm, "Failed to turn on pixel bvb clock: %d\n", ret);
goto err_disable_pixel_clock;
}
if (vc4_hdmi->variant->phy_init)
- vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state);
+ vc4_hdmi->variant->phy_init(vc4_hdmi, conn_state);
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
@@ -1841,7 +1572,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_device *drm = vc4_hdmi->connector.dev;
+ struct drm_connector *connector = &vc4_hdmi->connector;
+ struct drm_device *drm = connector->dev;
const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -1907,7 +1639,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
vc4_hdmi->packet_ram_enabled = true;
- vc4_hdmi_set_infoframes(encoder);
+ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
}
vc4_hdmi_recenter_fifo(vc4_hdmi);
@@ -1924,108 +1656,21 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(conn_state);
mutex_lock(&vc4_hdmi->mutex);
drm_mode_copy(&vc4_hdmi->saved_adjusted_mode,
&crtc_state->adjusted_mode);
- vc4_hdmi->output_bpc = vc4_state->output_bpc;
- vc4_hdmi->output_format = vc4_state->output_format;
+ vc4_hdmi->output_bpc = conn_state->hdmi.output_bpc;
+ vc4_hdmi->output_format = conn_state->hdmi.output_format;
mutex_unlock(&vc4_hdmi->mutex);
}
-static bool
-vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi,
- const struct drm_display_info *info,
- const struct drm_display_mode *mode,
- unsigned int format, unsigned int bpc)
-{
- struct drm_device *dev = vc4_hdmi->connector.dev;
- u8 vic = drm_match_cea_mode(mode);
-
- if (vic == 1 && bpc != 8) {
- drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
- return false;
- }
-
- if (!info->is_hdmi &&
- (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) {
- drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n");
- return false;
- }
-
- switch (format) {
- case VC4_HDMI_OUTPUT_RGB:
- drm_dbg(dev, "RGB Format, checking the constraints.\n");
-
- if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
- return false;
-
- if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {
- drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
- return false;
- }
-
- if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {
- drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
- return false;
- }
-
- drm_dbg(dev, "RGB format supported in that configuration.\n");
-
- return true;
-
- case VC4_HDMI_OUTPUT_YUV422:
- drm_dbg(dev, "YUV422 format, checking the constraints.\n");
-
- if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
- drm_dbg(dev, "Sink doesn't support YUV422.\n");
- return false;
- }
-
- if (bpc != 12) {
- drm_dbg(dev, "YUV422 only supports 12 bpc.\n");
- return false;
- }
-
- drm_dbg(dev, "YUV422 format supported in that configuration.\n");
-
- return true;
-
- case VC4_HDMI_OUTPUT_YUV444:
- drm_dbg(dev, "YUV444 format, checking the constraints.\n");
-
- if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
- drm_dbg(dev, "Sink doesn't support YUV444.\n");
- return false;
- }
-
- if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) {
- drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
- return false;
- }
-
- if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) {
- drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
- return false;
- }
-
- drm_dbg(dev, "YUV444 format supported in that configuration.\n");
-
- return true;
- }
-
- return false;
-}
-
static enum drm_mode_status
-vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
- const struct drm_display_mode *mode,
- unsigned long long clock)
+vc4_hdmi_connector_clock_valid(const struct drm_connector *connector,
+ const struct drm_display_mode *mode,
+ unsigned long long clock)
{
- const struct drm_connector *connector = &vc4_hdmi->connector;
- const struct drm_display_info *info = &connector->display_info;
+ const struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
if (clock > vc4_hdmi->variant->max_pixel_clock)
@@ -2040,125 +1685,13 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
drm_mode_vrefresh(mode) >= 50)
return MODE_CLOCK_HIGH;
- if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
- return MODE_CLOCK_HIGH;
-
return MODE_OK;
}
-static unsigned long long
-vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
- unsigned int bpc,
- enum vc4_hdmi_output_format fmt)
-{
- unsigned long long clock = mode->clock * 1000ULL;
-
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
- clock = clock * 2;
-
- if (fmt == VC4_HDMI_OUTPUT_YUV422)
- bpc = 8;
-
- clock = clock * bpc;
- do_div(clock, 8);
-
- return clock;
-}
-
-static int
-vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state,
- const struct drm_display_mode *mode,
- unsigned int bpc, unsigned int fmt)
-{
- unsigned long long clock;
-
- clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
- if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, clock) != MODE_OK)
- return -EINVAL;
-
- vc4_state->tmds_char_rate = clock;
-
- return 0;
-}
-
-static int
-vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state,
- const struct drm_display_mode *mode,
- unsigned int bpc)
-{
- struct drm_device *dev = vc4_hdmi->connector.dev;
- const struct drm_connector *connector = &vc4_hdmi->connector;
- const struct drm_display_info *info = &connector->display_info;
- unsigned int format;
-
- drm_dbg(dev, "Trying with an RGB output\n");
-
- format = VC4_HDMI_OUTPUT_RGB;
- if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) {
- int ret;
-
- ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
- mode, bpc, format);
- if (!ret) {
- vc4_state->output_format = format;
- return 0;
- }
- }
-
- drm_dbg(dev, "Failed, Trying with an YUV422 output\n");
-
- format = VC4_HDMI_OUTPUT_YUV422;
- if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) {
- int ret;
-
- ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
- mode, bpc, format);
- if (!ret) {
- vc4_state->output_format = format;
- return 0;
- }
- }
-
- drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n");
-
- return -EINVAL;
-}
-
-static int
-vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state,
- const struct drm_display_mode *mode)
-{
- struct drm_device *dev = vc4_hdmi->connector.dev;
- struct drm_connector_state *conn_state = &vc4_state->base;
- unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12);
- unsigned int bpc;
- int ret;
-
- for (bpc = max_bpc; bpc >= 8; bpc -= 2) {
- drm_dbg(dev, "Trying with a %d bpc output\n", bpc);
-
- ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state,
- mode, bpc);
- if (ret)
- continue;
-
- vc4_state->output_bpc = bpc;
-
- drm_dbg(dev,
- "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n",
- mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
- vc4_state->output_bpc,
- vc4_hdmi_output_fmt_str(vc4_state->output_format),
- vc4_state->tmds_char_rate);
-
- break;
- }
-
- return ret;
-}
+static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs = {
+ .tmds_char_rate_valid = vc4_hdmi_connector_clock_valid,
+ .write_infoframe = vc4_hdmi_write_infoframe,
+};
#define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
#define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL
@@ -2168,16 +1701,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_connector *connector = &vc4_hdmi->connector;
- struct drm_connector_state *old_conn_state =
- drm_atomic_get_old_connector_state(conn_state->state, connector);
- struct vc4_hdmi_connector_state *old_vc4_state =
- conn_state_to_vc4_hdmi_conn_state(old_conn_state);
- struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
unsigned long long tmds_char_rate = mode->clock * 1000;
unsigned long long tmds_bit_rate;
- int ret;
if (vc4_hdmi->variant->unsupported_odd_h_timings) {
if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
@@ -2213,15 +1739,6 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
tmds_char_rate = mode->clock * 1000;
}
- ret = vc4_hdmi_encoder_compute_config(vc4_hdmi, vc4_state, mode);
- if (ret)
- return ret;
-
- /* vc4_hdmi_encoder_compute_config may have changed output_bpc and/or output_format */
- if (vc4_state->output_bpc != old_vc4_state->output_bpc ||
- vc4_state->output_format != old_vc4_state->output_format)
- crtc_state->mode_changed = true;
-
return 0;
}
@@ -2230,6 +1747,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
const struct drm_display_mode *mode)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+ unsigned long long rate;
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
!(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
@@ -2237,7 +1755,8 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
(mode->hsync_end % 2) || (mode->htotal % 2)))
return MODE_H_ILLEGAL;
- return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 1000);
+ rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ return vc4_hdmi_connector_clock_valid(&vc4_hdmi->connector, mode, rate);
}
static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
@@ -2429,7 +1948,6 @@ out:
static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
{
- struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
struct device *dev = &vc4_hdmi->pdev->dev;
unsigned long flags;
int ret;
@@ -2437,7 +1955,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
lockdep_assert_held(&vc4_hdmi->mutex);
vc4_hdmi->audio.streaming = false;
- ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO, false);
+ ret = vc4_hdmi_stop_packet(vc4_hdmi, HDMI_INFOFRAME_TYPE_AUDIO, false);
if (ret)
dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
@@ -2528,7 +2046,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
{
struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
struct drm_device *drm = vc4_hdmi->connector.dev;
- struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
+ struct drm_connector *connector = &vc4_hdmi->connector;
unsigned int sample_rate = params->sample_rate;
unsigned int channels = params->channels;
unsigned long flags;
@@ -2605,8 +2123,10 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
- memcpy(&vc4_hdmi->audio.infoframe, &params->cea, sizeof(params->cea));
- vc4_hdmi_set_audio_infoframe(encoder);
+ ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,
+ &params->cea);
+ if (ret)
+ goto out_dev_exit;
out_dev_exit:
drm_dev_exit(idx);
@@ -3431,13 +2951,13 @@ static int vc4_hdmi_init_resources(struct drm_device *drm,
if (IS_ERR(vc4_hdmi->pixel_clock)) {
ret = PTR_ERR(vc4_hdmi->pixel_clock);
if (ret != -EPROBE_DEFER)
- DRM_ERROR("Failed to get pixel clock\n");
+ drm_err(drm, "Failed to get pixel clock\n");
return ret;
}
vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
if (IS_ERR(vc4_hdmi->hsm_clock)) {
- DRM_ERROR("Failed to get HDMI state machine clock\n");
+ drm_err(drm, "Failed to get HDMI state machine clock\n");
return PTR_ERR(vc4_hdmi->hsm_clock);
}
vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
@@ -3521,31 +3041,31 @@ static int vc5_hdmi_init_resources(struct drm_device *drm,
vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
if (IS_ERR(vc4_hdmi->hsm_clock)) {
- DRM_ERROR("Failed to get HDMI state machine clock\n");
+ drm_err(drm, "Failed to get HDMI state machine clock\n");
return PTR_ERR(vc4_hdmi->hsm_clock);
}
vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");
if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {
- DRM_ERROR("Failed to get pixel bvb clock\n");
+ drm_err(drm, "Failed to get pixel bvb clock\n");
return PTR_ERR(vc4_hdmi->pixel_bvb_clock);
}
vc4_hdmi->audio_clock = devm_clk_get(dev, "audio");
if (IS_ERR(vc4_hdmi->audio_clock)) {
- DRM_ERROR("Failed to get audio clock\n");
+ drm_err(drm, "Failed to get audio clock\n");
return PTR_ERR(vc4_hdmi->audio_clock);
}
vc4_hdmi->cec_clock = devm_clk_get(dev, "cec");
if (IS_ERR(vc4_hdmi->cec_clock)) {
- DRM_ERROR("Failed to get CEC clock\n");
+ drm_err(drm, "Failed to get CEC clock\n");
return PTR_ERR(vc4_hdmi->cec_clock);
}
vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
if (IS_ERR(vc4_hdmi->reset)) {
- DRM_ERROR("Failed to get HDMI reset line\n");
+ drm_err(drm, "Failed to get HDMI reset line\n");
return PTR_ERR(vc4_hdmi->reset);
}
@@ -3701,14 +3221,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
if (!ddc_node) {
- DRM_ERROR("Failed to find ddc node in device tree\n");
+ drm_err(drm, "Failed to find ddc node in device tree\n");
return -ENODEV;
}
vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
of_node_put(ddc_node);
if (!vc4_hdmi->ddc) {
- DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
+ drm_err(drm, "Failed to get ddc i2c adapter by node\n");
return -EPROBE_DEFER;
}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 934d5d61485a..b37f1d2c3fe5 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -10,7 +10,6 @@
struct vc4_hdmi;
struct vc4_hdmi_register;
-struct vc4_hdmi_connector_state;
enum vc4_hdmi_phy_channel {
PHY_LANE_0 = 0,
@@ -76,7 +75,7 @@ struct vc4_hdmi_variant {
/* Callback to initialize the PHY according to the connector state */
void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_conn_state);
+ struct drm_connector_state *conn_state);
/* Callback to disable the PHY */
void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
@@ -110,19 +109,6 @@ struct vc4_hdmi_audio {
bool streaming;
};
-enum vc4_hdmi_output_format {
- VC4_HDMI_OUTPUT_RGB,
- VC4_HDMI_OUTPUT_YUV422,
- VC4_HDMI_OUTPUT_YUV444,
- VC4_HDMI_OUTPUT_YUV420,
-};
-
-enum vc4_hdmi_broadcast_rgb {
- VC4_HDMI_BROADCAST_RGB_AUTO,
- VC4_HDMI_BROADCAST_RGB_FULL,
- VC4_HDMI_BROADCAST_RGB_LIMITED,
-};
-
/* General HDMI hardware state. */
struct vc4_hdmi {
struct vc4_hdmi_audio audio;
@@ -135,8 +121,6 @@ struct vc4_hdmi {
struct delayed_work scrambling_work;
- struct drm_property *broadcast_rgb_property;
-
struct i2c_adapter *ddc;
void __iomem *hdmicore_regs;
void __iomem *hd_regs;
@@ -218,16 +202,17 @@ struct vc4_hdmi {
bool scdc_enabled;
/**
- * @output_bpc: Copy of @vc4_connector_state.output_bpc for use
- * outside of KMS hooks. Protected by @mutex.
+ * @output_bpc: Copy of @drm_connector_state.hdmi.output_bpc for
+ * use outside of KMS hooks. Protected by @mutex.
*/
unsigned int output_bpc;
/**
- * @output_format: Copy of @vc4_connector_state.output_format
- * for use outside of KMS hooks. Protected by @mutex.
+ * @output_format: Copy of
+ * @drm_connector_state.hdmi.output_format for use outside of
+ * KMS hooks. Protected by @mutex.
*/
- enum vc4_hdmi_output_format output_format;
+ enum hdmi_colorspace output_format;
};
#define connector_to_vc4_hdmi(_connector) \
@@ -240,25 +225,14 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
return container_of_const(_encoder, struct vc4_hdmi, encoder);
}
-struct vc4_hdmi_connector_state {
- struct drm_connector_state base;
- unsigned long long tmds_char_rate;
- unsigned int output_bpc;
- enum vc4_hdmi_output_format output_format;
- enum vc4_hdmi_broadcast_rgb broadcast_rgb;
-};
-
-#define conn_state_to_vc4_hdmi_conn_state(_state) \
- container_of_const(_state, struct vc4_hdmi_connector_state, base)
-
void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_conn_state);
+ struct drm_connector_state *conn_state);
void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_conn_state);
+ struct drm_connector_state *conn_state);
void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index ec24999bf96d..1f5507fc7a03 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -128,7 +128,7 @@
#define OSCILLATOR_FREQUENCY 54000000
void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *conn_state)
+ struct drm_connector_state *conn_state)
{
unsigned long flags;
@@ -361,11 +361,11 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
}
void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *conn_state)
+ struct drm_connector_state *conn_state)
{
const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
- unsigned long long pixel_freq = conn_state->tmds_char_rate;
+ unsigned long long pixel_freq = conn_state->hdmi.tmds_char_rate;
unsigned long long vco_freq;
unsigned char word_sel;
unsigned long flags;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 04af672caacb..2a835a5cff9d 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -191,8 +191,8 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
ret = drm_mm_insert_node(&hvs->dlist_mm, space, VC4_KERNEL_DWORDS);
if (ret) {
- DRM_ERROR("Failed to allocate space for filter kernel: %d\n",
- ret);
+ drm_err(&hvs->vc4->base, "Failed to allocate space for filter kernel: %d\n",
+ ret);
return ret;
}
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index 563b3dfeb9b9..ef93d8e22a35 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -76,7 +76,7 @@ vc4_overflow_mem_work(struct work_struct *work)
bin_bo_slot = vc4_v3d_get_bin_slot(vc4);
if (bin_bo_slot < 0) {
- DRM_ERROR("Couldn't allocate binner overflow mem\n");
+ drm_err(&vc4->base, "Couldn't allocate binner overflow mem\n");
goto complete;
}
diff --git a/drivers/gpu/drm/vc4/vc4_perfmon.c b/drivers/gpu/drm/vc4/vc4_perfmon.c
index c4ac2c946238..c00a5cc2316d 100644
--- a/drivers/gpu/drm/vc4/vc4_perfmon.c
+++ b/drivers/gpu/drm/vc4/vc4_perfmon.c
@@ -116,6 +116,11 @@ void vc4_perfmon_open_file(struct vc4_file *vc4file)
static int vc4_perfmon_idr_del(int id, void *elem, void *data)
{
struct vc4_perfmon *perfmon = elem;
+ struct vc4_dev *vc4 = (struct vc4_dev *)data;
+
+ /* If the active perfmon is being destroyed, stop it first */
+ if (perfmon == vc4->active_perfmon)
+ vc4_perfmon_stop(vc4, perfmon, false);
vc4_perfmon_put(perfmon);
@@ -130,7 +135,7 @@ void vc4_perfmon_close_file(struct vc4_file *vc4file)
return;
mutex_lock(&vc4file->perfmon.lock);
- idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, NULL);
+ idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, vc4);
idr_destroy(&vc4file->perfmon.idr);
mutex_unlock(&vc4file->perfmon.lock);
mutex_destroy(&vc4file->perfmon.lock);
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
index 04ac7805e6d5..bf5c4e36c94e 100644
--- a/drivers/gpu/drm/vc4/vc4_v3d.c
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -441,21 +441,9 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
vc4->v3d = v3d;
v3d->vc4 = vc4;
- v3d->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(v3d->clk)) {
- int ret = PTR_ERR(v3d->clk);
-
- if (ret == -ENOENT) {
- /* bcm2835 didn't have a clock reference in the DT. */
- ret = 0;
- v3d->clk = NULL;
- } else {
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get V3D clock: %d\n",
- ret);
- return ret;
- }
- }
+ v3d->clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(v3d->clk))
+ return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n");
ret = platform_get_irq(pdev, 0);
if (ret < 0)
@@ -471,8 +459,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
return ret;
if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
- DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
- V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0);
+ drm_err(drm, "V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
+ V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0);
ret = -EINVAL;
goto err_put_runtime_pm;
}
@@ -485,7 +473,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
ret = vc4_irq_install(drm, vc4->irq);
if (ret) {
- DRM_ERROR("Failed to install IRQ handler\n");
+ drm_err(drm, "Failed to install IRQ handler\n");
goto err_put_runtime_pm;
}
diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c
index 7dff3ca5af6b..0c17284bf6f5 100644
--- a/drivers/gpu/drm/vc4/vc4_validate.c
+++ b/drivers/gpu/drm/vc4/vc4_validate.c
@@ -65,7 +65,7 @@ utile_width(int cpp)
case 8:
return 2;
default:
- DRM_ERROR("unknown cpp: %d\n", cpp);
+ pr_err("unknown cpp: %d\n", cpp);
return 1;
}
}
@@ -82,7 +82,7 @@ utile_height(int cpp)
case 8:
return 4;
default:
- DRM_ERROR("unknown cpp: %d\n", cpp);
+ pr_err("unknown cpp: %d\n", cpp);
return 1;
}
}
@@ -390,8 +390,8 @@ validate_tile_binning_config(VALIDATE_ARGS)
bin_slot = vc4_v3d_get_bin_slot(vc4);
if (bin_slot < 0) {
if (bin_slot != -EINTR && bin_slot != -ERESTARTSYS) {
- DRM_ERROR("Failed to allocate binner memory: %d\n",
- bin_slot);
+ drm_err(dev, "Failed to allocate binner memory: %d\n",
+ bin_slot);
}
return bin_slot;
}
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 268f18b10ee0..eb64e881051e 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -234,6 +234,7 @@ enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_PAL_60,
VC4_VEC_TV_MODE_PAL_N,
VC4_VEC_TV_MODE_SECAM,
+ VC4_VEC_TV_MODE_MONOCHROME,
};
struct vc4_vec_tv_mode {
@@ -324,6 +325,22 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
.custom_freq = 0x29c71c72,
},
+ {
+ /* 50Hz mono */
+ .mode = DRM_MODE_TV_MODE_MONOCHROME,
+ .expected_htotal = 864,
+ .config0 = VEC_CONFIG0_PAL_BDGHI_STD | VEC_CONFIG0_BURDIS |
+ VEC_CONFIG0_CHRDIS,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+ },
+ {
+ /* 60Hz mono */
+ .mode = DRM_MODE_TV_MODE_MONOCHROME,
+ .expected_htotal = 858,
+ .config0 = VEC_CONFIG0_PAL_M_STD | VEC_CONFIG0_BURDIS |
+ VEC_CONFIG0_CHRDIS,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+ },
};
static inline const struct vc4_vec_tv_mode *
@@ -351,6 +368,7 @@ static const struct drm_prop_enum_list legacy_tv_mode_names[] = {
{ VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
{ VC4_VEC_TV_MODE_PAL_N, "PAL-N", },
{ VC4_VEC_TV_MODE_SECAM, "SECAM", },
+ { VC4_VEC_TV_MODE_MONOCHROME, "Mono", },
};
static enum drm_connector_status
@@ -406,6 +424,10 @@ vc4_vec_connector_set_property(struct drm_connector *connector,
state->tv.mode = DRM_MODE_TV_MODE_SECAM;
break;
+ case VC4_VEC_TV_MODE_MONOCHROME:
+ state->tv.mode = DRM_MODE_TV_MODE_MONOCHROME;
+ break;
+
default:
return -EINVAL;
}
@@ -453,6 +475,10 @@ vc4_vec_connector_get_property(struct drm_connector *connector,
*val = VC4_VEC_TV_MODE_SECAM;
break;
+ case DRM_MODE_TV_MODE_MONOCHROME:
+ *val = VC4_VEC_TV_MODE_MONOCHROME;
+ break;
+
default:
return -EINVAL;
}
@@ -503,6 +529,8 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC);
+ drm_connector_attach_tv_margin_properties(connector);
+
drm_connector_attach_encoder(connector, &vec->encoder.base);
return 0;
@@ -529,7 +557,7 @@ static void vc4_vec_encoder_disable(struct drm_encoder *encoder,
ret = pm_runtime_put(&vec->pdev->dev);
if (ret < 0) {
- DRM_ERROR("Failed to release power domain: %d\n", ret);
+ drm_err(drm, "Failed to release power domain: %d\n", ret);
goto err_dev_exit;
}
@@ -563,7 +591,7 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
ret = pm_runtime_resume_and_get(&vec->pdev->dev);
if (ret < 0) {
- DRM_ERROR("Failed to retain power domain: %d\n", ret);
+ drm_err(drm, "Failed to retain power domain: %d\n", ret);
goto err_dev_exit;
}
@@ -576,13 +604,13 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
*/
ret = clk_set_rate(vec->clock, 108000000);
if (ret) {
- DRM_ERROR("Failed to set clock rate: %d\n", ret);
+ drm_err(drm, "Failed to set clock rate: %d\n", ret);
goto err_put_runtime_pm;
}
ret = clk_prepare_enable(vec->clock);
if (ret) {
- DRM_ERROR("Failed to turn on core clock: %d\n", ret);
+ drm_err(drm, "Failed to turn on core clock: %d\n", ret);
goto err_put_runtime_pm;
}
@@ -754,7 +782,8 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
BIT(DRM_MODE_TV_MODE_PAL) |
BIT(DRM_MODE_TV_MODE_PAL_M) |
BIT(DRM_MODE_TV_MODE_PAL_N) |
- BIT(DRM_MODE_TV_MODE_SECAM));
+ BIT(DRM_MODE_TV_MODE_SECAM) |
+ BIT(DRM_MODE_TV_MODE_MONOCHROME));
if (ret)
return ret;
@@ -777,7 +806,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
if (IS_ERR(vec->clock)) {
ret = PTR_ERR(vec->clock);
if (ret != -EPROBE_DEFER)
- DRM_ERROR("Failed to get clock: %d\n", ret);
+ drm_err(drm, "Failed to get clock: %d\n", ret);
return ret;
}