mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
Replace the #include of <linux/mod_devicetable.h> by the more specific <linux/device-id/*.h> where applicable. For most cases the include can be dropped completely, only a few drivers need one or two headers added. Acked-by: Danilo Krummrich <dakr@kernel.org> Acked-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/1a3f2007c5c5dcf555c09a4035ce3ae8ef1b6c49.1782808461.git.u.kleine-koenig@baylibre.com Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
190 lines
5.0 KiB
C
190 lines
5.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (C) Rockchip Electronics Co., Ltd.
|
|
* Zheng Yang <zhengyang@rock-chips.com>
|
|
* Andy Yan <andy.yan@rock-chips.com>
|
|
*/
|
|
#include <linux/err.h>
|
|
#include <linux/hw_bitfield.h>
|
|
#include <linux/mfd/syscon.h>
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/regmap.h>
|
|
|
|
#include <drm/bridge/inno_hdmi.h>
|
|
#include <drm/drm_bridge_connector.h>
|
|
#include <drm/drm_managed.h>
|
|
#include <drm/drm_of.h>
|
|
|
|
#include "rockchip_drm_drv.h"
|
|
|
|
#define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16)
|
|
|
|
#define RK3036_GRF_SOC_CON2 0x148
|
|
#define RK3036_HDMI_PHSYNC BIT(4)
|
|
#define RK3036_HDMI_PVSYNC BIT(5)
|
|
|
|
enum inno_hdmi_dev_type {
|
|
RK3036_HDMI,
|
|
RK3128_HDMI,
|
|
};
|
|
|
|
struct inno_hdmi_connector_state {
|
|
struct drm_connector_state base;
|
|
unsigned int colorimetry;
|
|
};
|
|
|
|
struct rockchip_inno_hdmi {
|
|
struct inno_hdmi *base;
|
|
struct device *dev;
|
|
struct regmap *grf;
|
|
struct rockchip_encoder encoder;
|
|
};
|
|
|
|
static struct inno_hdmi_phy_config rk3036_hdmi_phy_configs[] = {
|
|
{ 74250000, 0x3f, 0xbb },
|
|
{ 165000000, 0x6f, 0xbb },
|
|
{ ~0UL, 0x00, 0x00 }
|
|
};
|
|
|
|
static struct inno_hdmi_phy_config rk3128_hdmi_phy_configs[] = {
|
|
{ 74250000, 0x3f, 0xaa },
|
|
{ 165000000, 0x5f, 0xaa },
|
|
{ ~0UL, 0x00, 0x00 }
|
|
};
|
|
|
|
static void inno_hdmi_rk3036_enable(struct device *dev, struct drm_display_mode *mode)
|
|
{
|
|
struct rockchip_inno_hdmi *hdmi = dev_get_drvdata(dev);
|
|
int value, psync;
|
|
|
|
psync = mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 : 0;
|
|
value = FIELD_PREP_WM16(RK3036_HDMI_PHSYNC, psync);
|
|
psync = mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 : 0;
|
|
value |= FIELD_PREP_WM16(RK3036_HDMI_PVSYNC, psync);
|
|
regmap_write(hdmi->grf, RK3036_GRF_SOC_CON2, value);
|
|
}
|
|
|
|
static int inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
|
|
struct drm_crtc_state *crtc_state,
|
|
struct drm_connector_state *conn_state)
|
|
{
|
|
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
|
|
|
|
s->output_mode = ROCKCHIP_OUT_MODE_P888;
|
|
s->output_type = DRM_MODE_CONNECTOR_HDMIA;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct drm_encoder_helper_funcs inno_hdmi_rockchip_encoder_helper_funcs = {
|
|
.atomic_check = inno_hdmi_encoder_atomic_check,
|
|
};
|
|
|
|
static int inno_hdmi_rockchip_bind(struct device *dev, struct device *master, void *data)
|
|
{
|
|
struct drm_device *drm = data;
|
|
struct drm_connector *connector;
|
|
struct drm_encoder *encoder;
|
|
struct rockchip_inno_hdmi *hdmi;
|
|
const struct inno_hdmi_plat_data *plat_data;
|
|
int ret;
|
|
|
|
hdmi = drmm_kzalloc(drm, sizeof(*hdmi), GFP_KERNEL);
|
|
if (!hdmi)
|
|
return -ENOMEM;
|
|
|
|
hdmi->dev = dev;
|
|
|
|
plat_data = of_device_get_match_data(hdmi->dev);
|
|
if (!plat_data)
|
|
return -EINVAL;
|
|
|
|
if (of_device_is_compatible(dev->of_node, "rockchip,rk3036-inno-hdmi")) {
|
|
hdmi->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
|
|
if (IS_ERR(hdmi->grf))
|
|
return dev_err_probe(dev,
|
|
PTR_ERR(hdmi->grf), "Unable to get rockchip,grf\n");
|
|
}
|
|
|
|
encoder = &hdmi->encoder.encoder;
|
|
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
|
|
|
|
/*
|
|
* If we failed to find the CRTC(s) which this encoder is
|
|
* supposed to be connected to, it's because the CRTC has
|
|
* not been registered yet. Defer probing, and hope that
|
|
* the required CRTC is added later.
|
|
*/
|
|
if (encoder->possible_crtcs == 0)
|
|
return -EPROBE_DEFER;
|
|
|
|
ret = drmm_encoder_init(drm, encoder, NULL, DRM_MODE_ENCODER_TMDS, NULL);
|
|
if (ret)
|
|
return ret;
|
|
|
|
drm_encoder_helper_add(encoder, &inno_hdmi_rockchip_encoder_helper_funcs);
|
|
|
|
dev_set_drvdata(dev, hdmi);
|
|
|
|
hdmi->base = inno_hdmi_bind(dev, encoder, plat_data);
|
|
|
|
connector = drm_bridge_connector_init(drm, encoder);
|
|
if (IS_ERR(connector)) {
|
|
ret = PTR_ERR(connector);
|
|
dev_err(hdmi->dev, "failed to init bridge connector: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct component_ops inno_hdmi_rockchip_ops = {
|
|
.bind = inno_hdmi_rockchip_bind,
|
|
};
|
|
|
|
static int inno_hdmi_rockchip_probe(struct platform_device *pdev)
|
|
{
|
|
return component_add(&pdev->dev, &inno_hdmi_rockchip_ops);
|
|
}
|
|
|
|
static void inno_hdmi_rockchip_remove(struct platform_device *pdev)
|
|
{
|
|
component_del(&pdev->dev, &inno_hdmi_rockchip_ops);
|
|
}
|
|
|
|
static const struct inno_hdmi_plat_ops rk3036_inno_hdmi_plat_ops = {
|
|
.enable = inno_hdmi_rk3036_enable,
|
|
};
|
|
|
|
static const struct inno_hdmi_plat_data rk3036_inno_hdmi_plat_data = {
|
|
.ops = &rk3036_inno_hdmi_plat_ops,
|
|
.phy_configs = rk3036_hdmi_phy_configs,
|
|
.default_phy_config = &rk3036_hdmi_phy_configs[1],
|
|
};
|
|
|
|
static const struct inno_hdmi_plat_data rk3128_inno_hdmi_plat_data = {
|
|
.phy_configs = rk3128_hdmi_phy_configs,
|
|
.default_phy_config = &rk3128_hdmi_phy_configs[1],
|
|
};
|
|
|
|
static const struct of_device_id inno_hdmi_rockchip_dt_ids[] = {
|
|
{ .compatible = "rockchip,rk3036-inno-hdmi",
|
|
.data = &rk3036_inno_hdmi_plat_data,
|
|
},
|
|
{ .compatible = "rockchip,rk3128-inno-hdmi",
|
|
.data = &rk3128_inno_hdmi_plat_data,
|
|
},
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, inno_hdmi_rockchip_dt_ids);
|
|
|
|
struct platform_driver inno_hdmi_driver = {
|
|
.probe = inno_hdmi_rockchip_probe,
|
|
.remove = inno_hdmi_rockchip_remove,
|
|
.driver = {
|
|
.name = "innohdmi-rockchip",
|
|
.of_match_table = inno_hdmi_rockchip_dt_ids,
|
|
},
|
|
};
|