Commit bef2c7bd authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm/tegra/for-4.3-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next

drm/tegra: Changes for v4.3-rc1

There are a bunch of non-critical fixes here that I've collected over
the past few months, but the biggest part is Tegra210 support, in the
DC, DSI and SOR/HDMI drivers.

Also this finally restores DPMS with atomic mode-setting, something
that has been broken since the conversion and which I had originally
expected to take far less longer to fix.

* tag 'drm/tegra/for-4.3-rc1' of git://anongit.freedesktop.org/tegra/linux: (41 commits)
  drm/tegra: sor: Add HDMI support
  drm/tegra: sor: Add Tegra210 eDP support
  drm/tegra: dc: Implement atomic DPMS
  drm/tegra: sor: Restore DPMS
  drm/tegra: dsi: Restore DPMS
  drm/tegra: hdmi: Restore DPMS
  drm/tegra: rgb: Restore DPMS
  drm/tegra: sor: Use DRM debugfs infrastructure for CRC
  drm/tegra: sor: Write correct head state registers
  drm/tegra: sor: Constify display mode
  drm/tegra: sor: Reset the correct debugfs fields
  drm/tegra: sor: Set minor after debugfs initialization
  drm/tegra: sor: Provide error messages in probe
  drm/tegra: sor: Rename registers for consistency
  drm/tegra: dpaux: Disable interrupt when detached
  drm/tegra: dpaux: Configure pads as I2C by default
  drm/tegra: dpaux: Provide error message in probe
  drm/tegra: dsi: Add Tegra210 support
  drm/tegra: dsi: Add Tegra132 support
  drm/tegra: dsi: Add Tegra124 support
  ...
parents 3ff8e509 459cc2c6
......@@ -197,9 +197,11 @@ of the following host1x client modules:
- sor: serial output resource
Required properties:
- compatible: For Tegra124, must contain "nvidia,tegra124-sor". Otherwise,
must contain '"nvidia,<chip>-sor", "nvidia,tegra124-sor"', where <chip>
is tegra132.
- compatible: Should be:
- "nvidia,tegra124-sor": for Tegra124 and Tegra132
- "nvidia,tegra132-sor": for Tegra132
- "nvidia,tegra210-sor": for Tegra210
- "nvidia,tegra210-sor1": for Tegra210
- reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt outputs from the controller.
- clocks: Must contain an entry for each entry in clock-names.
......
This diff is collapsed.
......@@ -86,6 +86,11 @@
#define DC_CMD_REG_ACT_CONTROL 0x043
#define DC_COM_CRC_CONTROL 0x300
#define DC_COM_CRC_CONTROL_ALWAYS (1 << 3)
#define DC_COM_CRC_CONTROL_FULL_FRAME (0 << 2)
#define DC_COM_CRC_CONTROL_ACTIVE_DATA (1 << 2)
#define DC_COM_CRC_CONTROL_WAIT (1 << 1)
#define DC_COM_CRC_CONTROL_ENABLE (1 << 0)
#define DC_COM_CRC_CHECKSUM 0x301
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
......@@ -114,15 +119,17 @@
#define DC_COM_CRC_CHECKSUM_LATCHED 0x329
#define DC_DISP_DISP_SIGNAL_OPTIONS0 0x400
#define H_PULSE_0_ENABLE (1 << 8)
#define H_PULSE_1_ENABLE (1 << 10)
#define H_PULSE_2_ENABLE (1 << 12)
#define H_PULSE0_ENABLE (1 << 8)
#define H_PULSE1_ENABLE (1 << 10)
#define H_PULSE2_ENABLE (1 << 12)
#define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE (1 << 29)
#define SOR1_TIMING_CYA (1 << 27)
#define SOR1_ENABLE (1 << 26)
#define SOR_ENABLE (1 << 25)
#define CURSOR_ENABLE (1 << 16)
......@@ -242,9 +249,20 @@
#define BASE_COLOR_SIZE565 (6 << 0)
#define BASE_COLOR_SIZE332 (7 << 0)
#define BASE_COLOR_SIZE888 (8 << 0)
#define DITHER_CONTROL_MASK (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
#define BASE_COLOR_SIZE_MASK (0xf << 0)
#define BASE_COLOR_SIZE_666 (0 << 0)
#define BASE_COLOR_SIZE_111 (1 << 0)
#define BASE_COLOR_SIZE_222 (2 << 0)
#define BASE_COLOR_SIZE_333 (3 << 0)
#define BASE_COLOR_SIZE_444 (4 << 0)
#define BASE_COLOR_SIZE_555 (5 << 0)
#define BASE_COLOR_SIZE_565 (6 << 0)
#define BASE_COLOR_SIZE_332 (7 << 0)
#define BASE_COLOR_SIZE_888 (8 << 0)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC1_H_QUALIFIER_NONE (1 << 16)
......
......@@ -294,26 +294,41 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
}
dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
if (IS_ERR(dpaux->rst))
if (IS_ERR(dpaux->rst)) {
dev_err(&pdev->dev, "failed to get reset control: %ld\n",
PTR_ERR(dpaux->rst));
return PTR_ERR(dpaux->rst);
}
dpaux->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dpaux->clk))
if (IS_ERR(dpaux->clk)) {
dev_err(&pdev->dev, "failed to get module clock: %ld\n",
PTR_ERR(dpaux->clk));
return PTR_ERR(dpaux->clk);
}
err = clk_prepare_enable(dpaux->clk);
if (err < 0)
if (err < 0) {
dev_err(&pdev->dev, "failed to enable module clock: %d\n",
err);
return err;
}
reset_control_deassert(dpaux->rst);
dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
if (IS_ERR(dpaux->clk_parent))
if (IS_ERR(dpaux->clk_parent)) {
dev_err(&pdev->dev, "failed to get parent clock: %ld\n",
PTR_ERR(dpaux->clk_parent));
return PTR_ERR(dpaux->clk_parent);
}
err = clk_prepare_enable(dpaux->clk_parent);
if (err < 0)
if (err < 0) {
dev_err(&pdev->dev, "failed to enable parent clock: %d\n",
err);
return err;
}
err = clk_set_rate(dpaux->clk_parent, 270000000);
if (err < 0) {
......@@ -323,8 +338,11 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
}
dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
if (IS_ERR(dpaux->vdd))
if (IS_ERR(dpaux->vdd)) {
dev_err(&pdev->dev, "failed to get VDD supply: %ld\n",
PTR_ERR(dpaux->vdd));
return PTR_ERR(dpaux->vdd);
}
err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0,
dev_name(dpaux->dev), dpaux);
......@@ -334,6 +352,8 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
return err;
}
disable_irq(dpaux->irq);
dpaux->aux.transfer = tegra_dpaux_transfer;
dpaux->aux.dev = &pdev->dev;
......@@ -341,6 +361,24 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
if (err < 0)
return err;
/*
* Assume that by default the DPAUX/I2C pads will be used for HDMI,
* so power them up and configure them in I2C mode.
*
* The DPAUX code paths reconfigure the pads in AUX mode, but there
* is no possibility to perform the I2C mode configuration in the
* HDMI path.
*/
value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_PADCTL);
value = DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV |
DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
DPAUX_HYBRID_PADCTL_MODE_I2C;
tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL);
/* enable and clear all interrupts */
value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT |
DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT;
......@@ -359,6 +397,12 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
static int tegra_dpaux_remove(struct platform_device *pdev)
{
struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);
u32 value;
/* make sure pads are powered down when not in use */
value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
drm_dp_aux_unregister(&dpaux->aux);
......@@ -376,6 +420,7 @@ static int tegra_dpaux_remove(struct platform_device *pdev)
}
static const struct of_device_id tegra_dpaux_of_match[] = {
{ .compatible = "nvidia,tegra210-dpaux", },
{ .compatible = "nvidia,tegra124-dpaux", },
{ },
};
......@@ -425,8 +470,10 @@ int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
enum drm_connector_status status;
status = tegra_dpaux_detect(dpaux);
if (status == connector_status_connected)
if (status == connector_status_connected) {
enable_irq(dpaux->irq);
return 0;
}
usleep_range(1000, 2000);
}
......@@ -439,6 +486,8 @@ int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
unsigned long timeout;
int err;
disable_irq(dpaux->irq);
err = regulator_disable(dpaux->vdd);
if (err < 0)
return err;
......
......@@ -57,6 +57,8 @@
#define DPAUX_DP_AUX_CONFIG 0x45
#define DPAUX_HYBRID_PADCTL 0x49
#define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV (1 << 15)
#define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV (1 << 14)
#define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2)
......
......@@ -171,8 +171,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
if (err < 0)
goto fbdev;
drm_mode_config_reset(drm);
/*
* We don't use the drm_irq_install() helpers provided by the DRM
* core, so we need to set this manually in order to allow the
......@@ -182,11 +180,14 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
/* syncpoints are used for full 32-bit hardware VBLANK counters */
drm->max_vblank_count = 0xffffffff;
drm->vblank_disable_allowed = true;
err = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (err < 0)
goto device;
drm_mode_config_reset(drm);
err = tegra_drm_fb_init(drm);
if (err < 0)
goto vblank;
......@@ -1037,9 +1038,8 @@ static int host1x_drm_resume(struct device *dev)
}
#endif
static const struct dev_pm_ops host1x_drm_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(host1x_drm_suspend, host1x_drm_resume)
};
static SIMPLE_DEV_PM_OPS(host1x_drm_pm_ops, host1x_drm_suspend,
host1x_drm_resume);
static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra20-dc", },
......@@ -1056,6 +1056,12 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra124-dc", },
{ .compatible = "nvidia,tegra124-sor", },
{ .compatible = "nvidia,tegra124-hdmi", },
{ .compatible = "nvidia,tegra124-dsi", },
{ .compatible = "nvidia,tegra132-dsi", },
{ .compatible = "nvidia,tegra210-dc", },
{ .compatible = "nvidia,tegra210-dsi", },
{ .compatible = "nvidia,tegra210-sor", },
{ .compatible = "nvidia,tegra210-sor1", },
{ /* sentinel */ }
};
......
......@@ -12,6 +12,7 @@
#include <uapi/drm/tegra_drm.h>
#include <linux/host1x.h>
#include <linux/of_gpio.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
......@@ -104,6 +105,13 @@ int tegra_drm_exit(struct tegra_drm *tegra);
struct tegra_dc_soc_info;
struct tegra_output;
struct tegra_dc_stats {
unsigned long frames;
unsigned long vblank;
unsigned long underflow;
unsigned long overflow;
};
struct tegra_dc {
struct host1x_client client;
struct host1x_syncpt *syncpt;
......@@ -121,6 +129,7 @@ struct tegra_dc {
struct tegra_output *rgb;
struct tegra_dc_stats stats;
struct list_head list;
struct drm_info_list *debugfs_files;
......@@ -200,6 +209,7 @@ struct tegra_output {
const struct edid *edid;
unsigned int hpd_irq;
int hpd_gpio;
enum of_gpio_flags hpd_gpio_flags;
struct drm_encoder encoder;
struct drm_connector connector;
......
......@@ -119,6 +119,16 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_dsi *dsi = node->info_ent->data;
struct drm_crtc *crtc = dsi->output.encoder.crtc;
struct drm_device *drm = node->minor->dev;
int err = 0;
drm_modeset_lock_all(drm);
if (!crtc || !crtc->state->active) {
err = -EBUSY;
goto unlock;
}
#define DUMP_REG(name) \
seq_printf(s, "%-32s %#05x %08x\n", #name, name, \
......@@ -208,7 +218,9 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data)
#undef DUMP_REG
return 0;
unlock:
drm_modeset_unlock_all(drm);
return err;
}
static struct drm_info_list debugfs_files[] = {
......@@ -548,14 +560,19 @@ static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
/* horizontal sync width */
hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
hsw -= 10;
/* horizontal back porch */
hbp = (mode->htotal - mode->hsync_end) * mul / div;
hbp -= 14;
if ((dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0)
hbp += hsw;
/* horizontal front porch */
hfp = (mode->hsync_start - mode->hdisplay) * mul / div;
/* subtract packet overhead */
hsw -= 10;
hbp -= 14;
hfp -= 8;
tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
......@@ -726,11 +743,6 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
tegra_dsi_soft_reset(dsi->slave);
}
static int tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
{
return 0;
}
static void tegra_dsi_connector_reset(struct drm_connector *connector)
{
struct tegra_dsi_state *state;
......@@ -757,7 +769,7 @@ tegra_dsi_connector_duplicate_state(struct drm_connector *connector)
}
static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
.dpms = tegra_dsi_connector_dpms,
.dpms = drm_atomic_helper_connector_dpms,
.reset = tegra_dsi_connector_reset,
.detect = tegra_output_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
......@@ -783,22 +795,48 @@ static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
.destroy = tegra_output_encoder_destroy,
};
static void tegra_dsi_encoder_dpms(struct drm_encoder *encoder, int mode)
static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
{
}
struct tegra_output *output = encoder_to_output(encoder);
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
struct tegra_dsi *dsi = to_dsi(output);
u32 value;
int err;
static void tegra_dsi_encoder_prepare(struct drm_encoder *encoder)
{
}
if (output->panel)
drm_panel_disable(output->panel);
static void tegra_dsi_encoder_commit(struct drm_encoder *encoder)
{
tegra_dsi_video_disable(dsi);
/*
* The following accesses registers of the display controller, so make
* sure it's only executed when the output is attached to one.
*/
if (dc) {
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
value &= ~DSI_ENABLE;
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
tegra_dc_commit(dc);
}
err = tegra_dsi_wait_idle(dsi, 100);
if (err < 0)
dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
tegra_dsi_soft_reset(dsi);
if (output->panel)
drm_panel_unprepare(output->panel);
tegra_dsi_disable(dsi);
return;
}
static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted)
static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
{
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct tegra_output *output = encoder_to_output(encoder);
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
struct tegra_dsi *dsi = to_dsi(output);
......@@ -836,45 +874,6 @@ static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder,
return;
}
static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
{
struct tegra_output *output = encoder_to_output(encoder);
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
struct tegra_dsi *dsi = to_dsi(output);
u32 value;
int err;
if (output->panel)
drm_panel_disable(output->panel);
tegra_dsi_video_disable(dsi);
/*
* The following accesses registers of the display controller, so make
* sure it's only executed when the output is attached to one.
*/
if (dc) {
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
value &= ~DSI_ENABLE;
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
tegra_dc_commit(dc);
}
err = tegra_dsi_wait_idle(dsi, 100);
if (err < 0)
dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
tegra_dsi_soft_reset(dsi);
if (output->panel)
drm_panel_unprepare(output->panel);
tegra_dsi_disable(dsi);
return;
}
static int
tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
......@@ -957,11 +956,8 @@ tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
}
static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
.dpms = tegra_dsi_encoder_dpms,
.prepare = tegra_dsi_encoder_prepare,
.commit = tegra_dsi_encoder_commit,
.mode_set = tegra_dsi_encoder_mode_set,
.disable = tegra_dsi_encoder_disable,
.enable = tegra_dsi_encoder_enable,
.atomic_check = tegra_dsi_encoder_atomic_check,
};
......@@ -993,6 +989,10 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
DSI_PAD_OUT_CLK(0x0);
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
return tegra_mipi_calibrate(dsi->mipi);
}
......@@ -1622,6 +1622,9 @@ static int tegra_dsi_remove(struct platform_device *pdev)
}
static const struct of_device_id tegra_dsi_of_match[] = {
{ .compatible = "nvidia,tegra210-dsi", },
{ .compatible = "nvidia,tegra132-dsi", },
{ .compatible = "nvidia,tegra124-dsi", },
{ .compatible = "nvidia,tegra114-dsi", },
{ },
};
......
......@@ -113,6 +113,10 @@
#define DSI_PAD_SLEW_DN(x) (((x) & 0x7) << 12)
#define DSI_PAD_SLEW_UP(x) (((x) & 0x7) << 16)
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
#define DSI_PAD_CONTROL_4 0x52
#define DSI_GANGED_MODE_CONTROL 0x53
#define DSI_GANGED_MODE_CONTROL_ENABLE (1 << 0)
......
......@@ -772,14 +772,8 @@ static bool tegra_output_is_hdmi(struct tegra_output *output)
return drm_detect_hdmi_monitor(edid);
}
static int tegra_hdmi_connector_dpms(struct drm_connector *connector,
int mode)
{
return 0;
}
static const struct drm_connector_funcs tegra_hdmi_connector_funcs = {
.dpms = tegra_hdmi_connector_dpms,
.dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.detect = tegra_output_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
......@@ -819,22 +813,27 @@ static const struct drm_encoder_funcs tegra_hdmi_encoder_funcs = {
.destroy = tegra_output_encoder_destroy,
};
static void tegra_hdmi_encoder_dpms(struct drm_encoder *encoder, int mode)
static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder)
{
}
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
u32 value;
static void tegra_hdmi_encoder_prepare(struct drm_encoder *encoder)
{
}
/*
* The following accesses registers of the display controller, so make
* sure it's only executed when the output is attached to one.
*/
if (dc) {
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
value &= ~HDMI_ENABLE;
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
static void tegra_hdmi_encoder_commit(struct drm_encoder *encoder)
{
tegra_dc_commit(dc);
}
}
static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted)
static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder)
{
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
struct tegra_output *output = encoder_to_output(encoder);
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
......@@ -873,13 +872,13 @@ static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder,
tegra_dc_writel(dc, VSYNC_H_POSITION(1),
DC_DISP_DISP_TIMING_OPTIONS);
tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE_888,
DC_DISP_DISP_COLOR_CONTROL);
/* video_preamble uses h_pulse2 */
pulse_start = 1 + h_sync_width + h_back_porch - 10;
tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
tegra_dc_writel(dc, H_PULSE2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
PULSE_LAST_END_A;
......@@ -1036,24 +1035,6 @@ static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder,
/* TODO: add HDCP support */
}
static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder)
{
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
u32 value;
/*
* The following accesses registers of the display controller, so make
* sure it's only executed when the output is attached to one.
*/
if (dc) {
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
value &= ~HDMI_ENABLE;
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
tegra_dc_commit(dc);
}
}
static int
tegra_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
......@@ -1076,11 +1057,8 @@ tegra_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
}
static const struct drm_encoder_helper_funcs tegra_hdmi_encoder_helper_funcs = {
.dpms = tegra_hdmi_encoder_dpms,
.prepare = tegra_hdmi_encoder_prepare,
.commit = tegra_hdmi_encoder_commit,
.mode_set = tegra_hdmi_encoder_mode_set,
.disable = tegra_hdmi_encoder_disable,
.enable = tegra_hdmi_encoder_enable,
.atomic_check = tegra_hdmi_encoder_atomic_check,
};
......@@ -1088,11 +1066,16 @@ static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_hdmi *hdmi = node->info_ent->data;
int err;
struct drm_crtc *crtc = hdmi->output.encoder.crtc;
struct drm_device *drm = node->minor->dev;
int err = 0;
err = clk_prepare_enable(hdmi->clk);
if (err)
return err;
drm_modeset_lock_all(drm);
if (!crtc || !crtc->state->active) {
err = -EBUSY;
goto unlock;
}
#define DUMP_REG(name) \
seq_printf(s, "%-56s %#05x %08x\n", #name, name, \
......@@ -1259,9 +1242,9 @@ static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
#undef DUMP_REG
clk_disable_unprepare(hdmi->clk);
return 0;
unlock:
drm_modeset_unlock_all(drm);
return err;
}
static struct drm_info_list debugfs_files[] = {
......
......@@ -7,8 +7,6 @@
* published by the Free Software Foundation.
*/
#include <linux/of_gpio.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_panel.h>
#include "drm.h"
......@@ -59,10 +57,17 @@ tegra_output_connector_detect(struct drm_connector *connector, bool force)
enum drm_connector_status status = connector_status_unknown;
if (gpio_is_valid(output->hpd_gpio)) {
if (gpio_get_value(output->hpd_gpio) == 0)
status = connector_status_disconnected;
else
status = connector_status_connected;
if (output->hpd_gpio_flags & OF_GPIO_ACTIVE_LOW) {
if (gpio_get_value(output->hpd_gpio) != 0)
status = connector_status_disconnected;
else
status = connector_status_connected;
} else {
if (gpio_get_value(output->hpd_gpio) == 0)
status = connector_status_disconnected;
else
status = connector_status_connected;
}
} else {
if (!output->panel)
status = connector_status_disconnected;
......@@ -97,7 +102,6 @@ static irqreturn_t hpd_irq(int irq, void *data)
int tegra_output_probe(struct tegra_output *output)
{
struct device_node *ddc, *panel;
enum of_gpio_flags flags;
int err, size;
if (!output->of_node)
......@@ -128,7 +132,7 @@ int tegra_output_probe(struct tegra_output *output)
output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
"nvidia,hpd-gpio", 0,
&flags);
&output->hpd_gpio_flags);
if (gpio_is_valid(output->hpd_gpio)) {
unsigned long flags;
......
......@@ -18,7 +18,6 @@
struct tegra_rgb {
struct tegra_output output;
struct tegra_dc *dc;
bool enabled;
struct clk *clk_parent;
struct clk *clk;
......@@ -88,14 +87,8 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
tegra_dc_writel(dc, table[i].value, table[i].offset);
}
static int tegra_rgb_connector_dpms(struct drm_connector *connector,
int mode)
{
return 0;
}
static const struct drm_connector_funcs tegra_rgb_connector_funcs = {
.dpms = tegra_rgb_connector_dpms,
.dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.detect = tegra_output_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
......@@ -126,21 +119,22 @@ static const struct drm_encoder_funcs tegra_rgb_encoder_funcs = {
.destroy = tegra_output_encoder_destroy,
};
static void tegra_rgb_encoder_dpms(struct drm_encoder *encoder, int mode)
static void tegra_rgb_encoder_disable(struct drm_encoder *encoder)
{
}
struct tegra_output *output = encoder_to_output(encoder);
struct tegra_rgb *rgb = to_rgb(output);
static void tegra_rgb_encoder_prepare(struct drm_encoder *encoder)
{
}
if (output->panel)
drm_panel_disable(output->panel);
static void tegra_rgb_encoder_commit(struct drm_encoder *encoder)
{
tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
tegra_dc_commit(rgb->dc);
if (output->panel)
drm_panel_unprepare(output->panel);
}
static void tegra_rgb_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted)
static void tegra_rgb_encoder_enable(struct drm_encoder *encoder)
{
struct tegra_output *output = encoder_to_output(encoder);
struct tegra_rgb *rgb = to_rgb(output);
......@@ -175,21 +169,6 @@ static void tegra_rgb_encoder_mode_set(struct drm_encoder *encoder,
drm_panel_enable(output->panel);
}
static void tegra_rgb_encoder_disable(struct drm_encoder *encoder)
{
struct tegra_output *output = encoder_to_output(encoder);
struct tegra_rgb *rgb = to_rgb(output);
if (output->panel)
drm_panel_disable(output->panel);
tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
tegra_dc_commit(rgb->dc);
if (output->panel)
drm_panel_unprepare(output->panel);
}
static int
tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
......@@ -232,11 +211,8 @@ tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder,
}
static const struct drm_encoder_helper_funcs tegra_rgb_encoder_helper_funcs = {
.dpms = tegra_rgb_encoder_dpms,
.prepare = tegra_rgb_encoder_prepare,
.commit = tegra_rgb_encoder_commit,
.mode_set = tegra_rgb_encoder_mode_set,
.disable = tegra_rgb_encoder_disable,
.enable = tegra_rgb_encoder_enable,
.atomic_check = tegra_rgb_encoder_atomic_check,
};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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