* [PATCH 1/3] drm/tegra: Align FB pitch
@ 2014-05-24 1:58 Stéphane Marchesin
2014-05-24 1:58 ` [PATCH 2/3] drm/tegra: Support setting the EMC clock Stéphane Marchesin
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Stéphane Marchesin @ 2014-05-24 1:58 UTC (permalink / raw)
To: dri-devel; +Cc: Stéphane Marchesin, treding
The display controller doesn't handle non-256 byte aligned buffer
pitches. If you give it an unaligned buffer, it will stop after the
first line and will report underflows in the debug registers
(DC_WINBUF_UFLOW_STATUS and friends). So let's make sure that all our
framebuffer pitches are 256-byte aligned.
Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
---
drivers/gpu/drm/tegra/drm.h | 2 ++
drivers/gpu/drm/tegra/fb.c | 3 ++-
drivers/gpu/drm/tegra/gem.c | 2 ++
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 126332c..6753598 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -251,6 +251,8 @@ static inline int tegra_output_check_mode(struct tegra_output *output,
return output ? -ENOSYS : -EINVAL;
}
+#define DC_PITCH_ALIGNMENT 256
+
/* from bus.c */
int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device);
void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device);
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index f7fca09..691e83e 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -207,7 +207,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
cmd.width = sizes->surface_width;
cmd.height = sizes->surface_height;
- cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+ cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel,
+ DC_PITCH_ALIGNMENT);
cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index bcf9895..9a92a9b 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -16,6 +16,7 @@
#include <linux/dma-buf.h>
#include <drm/tegra_drm.h>
+#include "drm.h"
#include "gem.h"
static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
@@ -260,6 +261,7 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
struct tegra_bo *bo;
+ min_pitch = round_up(min_pitch, DC_PITCH_ALIGNMENT);
if (args->pitch < min_pitch)
args->pitch = min_pitch;
--
1.9.1.423.g4596e3a
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] drm/tegra: Support setting the EMC clock
2014-05-24 1:58 [PATCH 1/3] drm/tegra: Align FB pitch Stéphane Marchesin
@ 2014-05-24 1:58 ` Stéphane Marchesin
2014-05-26 9:07 ` Lucas Stach
2014-05-24 1:58 ` [PATCH 3/3] drm/tegra: Don't hardcode link parameters Stéphane Marchesin
2014-06-05 9:40 ` [PATCH 1/3] drm/tegra: Align FB pitch Thierry Reding
2 siblings, 1 reply; 8+ messages in thread
From: Stéphane Marchesin @ 2014-05-24 1:58 UTC (permalink / raw)
To: dri-devel; +Cc: Stéphane Marchesin, treding
The current code doesn't enable the EMC clock, without which the
display cannot function, so let's enable this clock. We also need a
bit of code to pick the right frequency for the EMC clock depending
on the current video mode settings.
Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
---
drivers/gpu/drm/tegra/dc.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/tegra/drm.h | 1 +
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index edb871d..f398dfb 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -325,6 +325,9 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
}
drm_vblank_off(drm, dc->pipe);
+
+ if (dc->emc_clk)
+ clk_set_rate(dc->emc_clk, 0);
}
static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -640,6 +643,50 @@ unsigned int tegra_dc_format(uint32_t format)
return WIN_COLOR_DEPTH_B8G8R8A8;
}
+static unsigned long tegra_emc_bw_to_freq_req(unsigned long bw)
+{
+ int bytes_per_emc_clock;
+
+ if (of_machine_is_compatible("nvidia,tegra124"))
+ bytes_per_emc_clock = 16;
+ else
+ bytes_per_emc_clock = 8;
+
+ return (bw + bytes_per_emc_clock - 1) / bytes_per_emc_clock;
+}
+
+#define EMC_FREQ_CUTOFF_USE_130_PERCENT 100000000UL
+#define EMC_FREQ_CUTOFF_USE_140_PERCENT 50000000UL
+
+static int tegra_dc_program_bandwidth(struct tegra_dc *dc,
+ struct drm_display_mode *mode,
+ struct tegra_dc_window *window)
+{
+ unsigned long bandwidth = mode->clock * window->bits_per_pixel / 8;
+ unsigned long freq;
+ struct clk *emc_master;
+
+ if (!dc->emc_clk)
+ return 0;
+
+ emc_master = clk_get_parent(dc->emc_clk);
+ freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
+ freq = clk_round_rate(emc_master, freq);
+
+ /* XXX: Add safety margins for DVFS */
+
+ if (freq < EMC_FREQ_CUTOFF_USE_140_PERCENT)
+ bandwidth += 4 * bandwidth / 10;
+ else if (freq < EMC_FREQ_CUTOFF_USE_130_PERCENT)
+ bandwidth += 3 * bandwidth / 10;
+ else
+ bandwidth += bandwidth / 10;
+
+ freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
+
+ return clk_set_rate(dc->emc_clk, freq);
+}
+
static int tegra_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted,
@@ -691,7 +738,11 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
if (err < 0)
dev_err(dc->dev, "failed to enable root plane\n");
- return 0;
+ err = tegra_dc_program_bandwidth(dc, mode, &window);
+ if (err)
+ dev_err(dc->dev, "failed to program the EMC clock\n");
+
+ return err;
}
static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
@@ -1260,6 +1311,12 @@ static int tegra_dc_probe(struct platform_device *pdev)
if (err < 0)
return err;
+ dc->emc_clk = devm_clk_get(&pdev->dev, "emc");
+ if (IS_ERR(dc->emc_clk))
+ dc->emc_clk = NULL;
+ else
+ clk_prepare_enable(dc->emc_clk);
+
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dc->regs = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(dc->regs))
@@ -1312,6 +1369,8 @@ static int tegra_dc_remove(struct platform_device *pdev)
}
clk_disable_unprepare(dc->clk);
+ if (dc->emc_clk)
+ clk_disable_unprepare(dc->emc_clk);
return 0;
}
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 6753598..30d91c0 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -101,6 +101,7 @@ struct tegra_dc {
struct clk *clk;
struct reset_control *rst;
+ struct clk *emc_clk;
void __iomem *regs;
int irq;
--
1.9.1.423.g4596e3a
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] drm/tegra: Don't hardcode link parameters
2014-05-24 1:58 [PATCH 1/3] drm/tegra: Align FB pitch Stéphane Marchesin
2014-05-24 1:58 ` [PATCH 2/3] drm/tegra: Support setting the EMC clock Stéphane Marchesin
@ 2014-05-24 1:58 ` Stéphane Marchesin
2014-06-05 9:40 ` [PATCH 1/3] drm/tegra: Align FB pitch Thierry Reding
2 siblings, 0 replies; 8+ messages in thread
From: Stéphane Marchesin @ 2014-05-24 1:58 UTC (permalink / raw)
To: dri-devel; +Cc: Stéphane Marchesin, treding
The currently hardcoded link parameters don't work on my eDP display,
however the android driver has code to compute the parameters. This is
a port of this code to the drm driver which allows the drm driver to
compute the link parameters correctly.
Note that we still hardcode the bpp, this will be taken care of in
another patch.
Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
---
drivers/gpu/drm/tegra/sor.c | 199 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 190 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 23fb9b1..1fbb488 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -289,12 +289,175 @@ static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
return -ETIMEDOUT;
}
+struct tegra_sor_dp_link {
+ u32 bits_per_pixel;
+
+ u32 activepolarity;
+ u32 active_count;
+ u32 tu_size;
+ u32 active_frac;
+ u32 watermark;
+};
+
+static int tegra_sor_calc_config(struct tegra_sor *sor,
+ struct drm_display_mode *mode,
+ struct tegra_sor_dp_link *tegra_link,
+ struct drm_dp_link *link)
+{
+ const u32 link_rate = link->rate * 1000;
+ const u64 f = 100000; /* precision factor */
+ const int pclk = mode->clock * 1000;
+
+ u32 num_linkclk_line; /* Number of link clocks per line */
+ u64 ratio_f; /* Ratio of incoming to outgoing data rate */
+ u64 frac_f;
+ u64 activesym_f; /* Activesym per TU */
+ u64 activecount_f;
+ u32 activecount;
+ u32 activepolarity;
+ u64 approx_value_f;
+ u32 activefrac = 0;
+ u64 accumulated_error_f = 0;
+ u32 lowest_neg_activecount = 0;
+ u32 lowest_neg_activepolarity = 0;
+ u32 lowest_neg_tusize = 64;
+ u32 num_symbols_per_line;
+ u64 lowest_neg_activefrac = 0;
+ u64 lowest_neg_error_f = 64 * f;
+ u64 watermark_f;
+
+ int i;
+ bool neg;
+
+ if (!link_rate || !link->num_lanes || !pclk ||
+ !tegra_link->bits_per_pixel)
+ return -1;
+
+ if ((u64)pclk * tegra_link->bits_per_pixel >=
+ (u64)link_rate * 8 * link->num_lanes)
+ return -1;
+
+ num_linkclk_line = div_u64((u64)link_rate * mode->hdisplay, pclk);
+
+ ratio_f = (u64)pclk * tegra_link->bits_per_pixel * f;
+ ratio_f /= 8;
+ ratio_f = div_u64(ratio_f, link_rate * link->num_lanes);
+
+ for (i = 64; i >= 32; --i) {
+ activesym_f = ratio_f * i;
+ activecount_f = div_u64(activesym_f, (u32)f) * f;
+ frac_f = activesym_f - activecount_f;
+ activecount = (u32)div_u64(activecount_f, (u32)f);
+
+ if (frac_f < (f / 2)) /* fraction < 0.5 */
+ activepolarity = 0;
+ else {
+ activepolarity = 1;
+ frac_f = f - frac_f;
+ }
+
+ if (frac_f != 0) {
+ frac_f = div_u64((f * f), frac_f); /* 1/fraction */
+ if (frac_f > (15 * f))
+ activefrac = activepolarity ? 1 : 15;
+ else
+ activefrac = activepolarity ?
+ (u32)div_u64(frac_f, (u32)f) + 1 :
+ (u32)div_u64(frac_f, (u32)f);
+ }
+
+ if (activefrac == 1)
+ activepolarity = 0;
+
+ if (activepolarity == 1)
+ approx_value_f = activefrac ? div_u64(
+ activecount_f + (activefrac * f - f) * f,
+ (activefrac * f)) :
+ activecount_f + f;
+ else
+ approx_value_f = activefrac ?
+ activecount_f + div_u64(f, activefrac) :
+ activecount_f;
+
+ if (activesym_f < approx_value_f) {
+ accumulated_error_f = num_linkclk_line *
+ div_u64(approx_value_f - activesym_f, i);
+ neg = true;
+ } else {
+ accumulated_error_f = num_linkclk_line *
+ div_u64(activesym_f - approx_value_f, i);
+ neg = false;
+ }
+
+ if ((neg && (lowest_neg_error_f > accumulated_error_f)) ||
+ (accumulated_error_f == 0)) {
+ lowest_neg_error_f = accumulated_error_f;
+ lowest_neg_tusize = i;
+ lowest_neg_activecount = activecount;
+ lowest_neg_activepolarity = activepolarity;
+ lowest_neg_activefrac = activefrac;
+
+ if (accumulated_error_f == 0)
+ break;
+ }
+ }
+
+ if (lowest_neg_activefrac == 0) {
+ tegra_link->activepolarity = 0;
+ tegra_link->active_count = lowest_neg_activepolarity ?
+ lowest_neg_activecount : lowest_neg_activecount - 1;
+ tegra_link->tu_size = lowest_neg_tusize;
+ tegra_link->active_frac = 1;
+ } else {
+ tegra_link->activepolarity = lowest_neg_activepolarity;
+ tegra_link->active_count = (u32)lowest_neg_activecount;
+ tegra_link->tu_size = lowest_neg_tusize;
+ tegra_link->active_frac = (u32)lowest_neg_activefrac;
+ }
+
+ dev_dbg(sor->dev,
+ "dp: sor configuration: polarity: %d active count: %d "
+ "tu size: %d, active frac: %d\n",
+ tegra_link->activepolarity,
+ tegra_link->active_count,
+ tegra_link->tu_size,
+ tegra_link->active_frac);
+
+ watermark_f = div_u64(ratio_f * tegra_link->tu_size * (f - ratio_f), f);
+ tegra_link->watermark = (u32)div_u64(watermark_f + lowest_neg_error_f,
+ f) + tegra_link->bits_per_pixel / 4 - 1;
+ num_symbols_per_line = (mode->hdisplay * tegra_link->bits_per_pixel) /
+ (8 * link->num_lanes);
+ if (tegra_link->watermark > 30) {
+ dev_dbg(sor->dev,
+ "dp: sor setting: unable to get a good tusize, "
+ "force watermark to 30.\n");
+ tegra_link->watermark = 30;
+
+ return -1;
+ } else if (tegra_link->watermark > num_symbols_per_line) {
+ dev_dbg(sor->dev,
+ "dp: sor setting: force watermark to the number "
+ "of symbols in the line.\n");
+ tegra_link->watermark = num_symbols_per_line;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
static int tegra_output_sor_enable(struct tegra_output *output)
{
struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
struct drm_display_mode *mode = &dc->base.mode;
unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
struct tegra_sor *sor = to_sor(output);
+ struct tegra_sor_dp_link tegra_link;
+ /* FIXME: properly convert to struct drm_dp_aux */
+ struct drm_dp_aux *aux = (struct drm_dp_aux *)sor->dpaux;
+ struct drm_dp_link link;
unsigned long value;
int err;
@@ -311,12 +474,23 @@ static int tegra_output_sor_enable(struct tegra_output *output)
err = tegra_dpaux_enable(sor->dpaux);
if (err < 0)
dev_err(sor->dev, "failed to enable DP: %d\n", err);
+
+ err = drm_dp_link_probe(aux, &link);
+ if (err < 0) {
+ dev_err(sor->dev, "failed to probe eDP link: %d\n",
+ err);
+ return err;
+ }
}
err = clk_set_parent(sor->clk, sor->clk_safe);
if (err < 0)
dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
+ tegra_link.bits_per_pixel = 24; /* XXX: don't hardcode? */
+
+ err = tegra_sor_calc_config(sor, mode, &tegra_link, &link);
+
value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
@@ -454,7 +628,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
value |= SOR_DP_LINKCTL_ENABLE;
value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
- value |= SOR_DP_LINKCTL_TU_SIZE(59); /* XXX: don't hardcode? */
+ value |= SOR_DP_LINKCTL_TU_SIZE(tegra_link.tu_size);
value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
@@ -470,13 +644,13 @@ static int tegra_output_sor_enable(struct tegra_output *output)
value = tegra_sor_readl(sor, SOR_DP_CONFIG_0);
value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
- value |= SOR_DP_CONFIG_WATERMARK(14); /* XXX: don't hardcode? */
+ value |= SOR_DP_CONFIG_WATERMARK(tegra_link.watermark);
value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
- value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(47); /* XXX: don't hardcode? */
+ value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(tegra_link.active_count);
value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
- value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(9); /* XXX: don't hardcode? */
+ value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(tegra_link.active_frac);
value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY; /* XXX: don't hardcode? */
@@ -500,9 +674,6 @@ static int tegra_output_sor_enable(struct tegra_output *output)
tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
if (sor->dpaux) {
- /* FIXME: properly convert to struct drm_dp_aux */
- struct drm_dp_aux *aux = (struct drm_dp_aux *)sor->dpaux;
- struct drm_dp_link link;
u8 rate, lanes;
err = drm_dp_link_probe(aux, &link);
@@ -586,12 +757,22 @@ static int tegra_output_sor_enable(struct tegra_output *output)
* configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
* raster, associate with display controller)
*/
- value = SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 |
- SOR_STATE_ASY_VSYNCPOL |
+ value = SOR_STATE_ASY_VSYNCPOL |
SOR_STATE_ASY_HSYNCPOL |
SOR_STATE_ASY_PROTOCOL_DP_A |
SOR_STATE_ASY_CRC_MODE_COMPLETE |
SOR_STATE_ASY_OWNER(dc->pipe + 1);
+ switch (tegra_link.bits_per_pixel) {
+ default:
+ dev_err(sor->dev, "dp: unknown BPP value\n");
+ case 24:
+ value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
+ break;
+ case 18:
+ value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
+ break;
+ }
+
tegra_sor_writel(sor, value, SOR_STATE_1);
/*
--
1.9.1.423.g4596e3a
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] drm/tegra: Support setting the EMC clock
2014-05-24 1:58 ` [PATCH 2/3] drm/tegra: Support setting the EMC clock Stéphane Marchesin
@ 2014-05-26 9:07 ` Lucas Stach
2014-05-26 9:28 ` Stéphane Marchesin
0 siblings, 1 reply; 8+ messages in thread
From: Lucas Stach @ 2014-05-26 9:07 UTC (permalink / raw)
To: Stéphane Marchesin; +Cc: treding, dri-devel
Am Freitag, den 23.05.2014, 18:58 -0700 schrieb Stéphane Marchesin:
> The current code doesn't enable the EMC clock, without which the
> display cannot function, so let's enable this clock. We also need a
> bit of code to pick the right frequency for the EMC clock depending
> on the current video mode settings.
>
That's not the right way to do it. The DRM driver has no business
controlling the EMC clock directly. This should be done through a real
EMC driver plus some kind of bus QoS, where DC is just one client.
Regards,
Lucas
> Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
> ---
> drivers/gpu/drm/tegra/dc.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/tegra/drm.h | 1 +
> 2 files changed, 61 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index edb871d..f398dfb 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -325,6 +325,9 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
> }
>
> drm_vblank_off(drm, dc->pipe);
> +
> + if (dc->emc_clk)
> + clk_set_rate(dc->emc_clk, 0);
> }
>
> static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
> @@ -640,6 +643,50 @@ unsigned int tegra_dc_format(uint32_t format)
> return WIN_COLOR_DEPTH_B8G8R8A8;
> }
>
> +static unsigned long tegra_emc_bw_to_freq_req(unsigned long bw)
> +{
> + int bytes_per_emc_clock;
> +
> + if (of_machine_is_compatible("nvidia,tegra124"))
> + bytes_per_emc_clock = 16;
> + else
> + bytes_per_emc_clock = 8;
> +
> + return (bw + bytes_per_emc_clock - 1) / bytes_per_emc_clock;
> +}
> +
> +#define EMC_FREQ_CUTOFF_USE_130_PERCENT 100000000UL
> +#define EMC_FREQ_CUTOFF_USE_140_PERCENT 50000000UL
> +
> +static int tegra_dc_program_bandwidth(struct tegra_dc *dc,
> + struct drm_display_mode *mode,
> + struct tegra_dc_window *window)
> +{
> + unsigned long bandwidth = mode->clock * window->bits_per_pixel / 8;
> + unsigned long freq;
> + struct clk *emc_master;
> +
> + if (!dc->emc_clk)
> + return 0;
> +
> + emc_master = clk_get_parent(dc->emc_clk);
> + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> + freq = clk_round_rate(emc_master, freq);
> +
> + /* XXX: Add safety margins for DVFS */
> +
> + if (freq < EMC_FREQ_CUTOFF_USE_140_PERCENT)
> + bandwidth += 4 * bandwidth / 10;
> + else if (freq < EMC_FREQ_CUTOFF_USE_130_PERCENT)
> + bandwidth += 3 * bandwidth / 10;
> + else
> + bandwidth += bandwidth / 10;
> +
> + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> +
> + return clk_set_rate(dc->emc_clk, freq);
> +}
> +
> static int tegra_crtc_mode_set(struct drm_crtc *crtc,
> struct drm_display_mode *mode,
> struct drm_display_mode *adjusted,
> @@ -691,7 +738,11 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
> if (err < 0)
> dev_err(dc->dev, "failed to enable root plane\n");
>
> - return 0;
> + err = tegra_dc_program_bandwidth(dc, mode, &window);
> + if (err)
> + dev_err(dc->dev, "failed to program the EMC clock\n");
> +
> + return err;
> }
>
> static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> @@ -1260,6 +1311,12 @@ static int tegra_dc_probe(struct platform_device *pdev)
> if (err < 0)
> return err;
>
> + dc->emc_clk = devm_clk_get(&pdev->dev, "emc");
> + if (IS_ERR(dc->emc_clk))
> + dc->emc_clk = NULL;
> + else
> + clk_prepare_enable(dc->emc_clk);
> +
> regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> dc->regs = devm_ioremap_resource(&pdev->dev, regs);
> if (IS_ERR(dc->regs))
> @@ -1312,6 +1369,8 @@ static int tegra_dc_remove(struct platform_device *pdev)
> }
>
> clk_disable_unprepare(dc->clk);
> + if (dc->emc_clk)
> + clk_disable_unprepare(dc->emc_clk);
>
> return 0;
> }
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index 6753598..30d91c0 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -101,6 +101,7 @@ struct tegra_dc {
>
> struct clk *clk;
> struct reset_control *rst;
> + struct clk *emc_clk;
> void __iomem *regs;
> int irq;
>
--
Pengutronix e.K. | Lucas Stach |
Industrial Linux Solutions | http://www.pengutronix.de/ |
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] drm/tegra: Support setting the EMC clock
2014-05-26 9:07 ` Lucas Stach
@ 2014-05-26 9:28 ` Stéphane Marchesin
[not found] ` <CACP_E+J-sCsiiSX-apX3ZqWFHVGxgN5FG9eu9-qTjLQHF22DwA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 8+ messages in thread
From: Stéphane Marchesin @ 2014-05-26 9:28 UTC (permalink / raw)
To: Lucas Stach
Cc: Stéphane Marchesin, treding, dri-devel@lists.freedesktop.org
[-- Attachment #1.1: Type: text/plain, Size: 5414 bytes --]
On Mon, May 26, 2014 at 2:07 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> Am Freitag, den 23.05.2014, 18:58 -0700 schrieb Stéphane Marchesin:
> > The current code doesn't enable the EMC clock, without which the
> > display cannot function, so let's enable this clock. We also need a
> > bit of code to pick the right frequency for the EMC clock depending
> > on the current video mode settings.
> >
> That's not the right way to do it. The DRM driver has no business
> controlling the EMC clock directly. This should be done through a real
> EMC driver plus some kind of bus QoS, where DC is just one client.
>
I thought about it but didn't see another consumer in upstream kernels. Who
are the other consumers of EMC?
Stéphane
> Regards,
> Lucas
>
> > Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
> > ---
> > drivers/gpu/drm/tegra/dc.c | 61
> ++++++++++++++++++++++++++++++++++++++++++++-
> > drivers/gpu/drm/tegra/drm.h | 1 +
> > 2 files changed, 61 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> > index edb871d..f398dfb 100644
> > --- a/drivers/gpu/drm/tegra/dc.c
> > +++ b/drivers/gpu/drm/tegra/dc.c
> > @@ -325,6 +325,9 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
> > }
> >
> > drm_vblank_off(drm, dc->pipe);
> > +
> > + if (dc->emc_clk)
> > + clk_set_rate(dc->emc_clk, 0);
> > }
> >
> > static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
> > @@ -640,6 +643,50 @@ unsigned int tegra_dc_format(uint32_t format)
> > return WIN_COLOR_DEPTH_B8G8R8A8;
> > }
> >
> > +static unsigned long tegra_emc_bw_to_freq_req(unsigned long bw)
> > +{
> > + int bytes_per_emc_clock;
> > +
> > + if (of_machine_is_compatible("nvidia,tegra124"))
> > + bytes_per_emc_clock = 16;
> > + else
> > + bytes_per_emc_clock = 8;
> > +
> > + return (bw + bytes_per_emc_clock - 1) / bytes_per_emc_clock;
> > +}
> > +
> > +#define EMC_FREQ_CUTOFF_USE_130_PERCENT 100000000UL
> > +#define EMC_FREQ_CUTOFF_USE_140_PERCENT 50000000UL
> > +
> > +static int tegra_dc_program_bandwidth(struct tegra_dc *dc,
> > + struct drm_display_mode *mode,
> > + struct tegra_dc_window *window)
> > +{
> > + unsigned long bandwidth = mode->clock * window->bits_per_pixel / 8;
> > + unsigned long freq;
> > + struct clk *emc_master;
> > +
> > + if (!dc->emc_clk)
> > + return 0;
> > +
> > + emc_master = clk_get_parent(dc->emc_clk);
> > + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> > + freq = clk_round_rate(emc_master, freq);
> > +
> > + /* XXX: Add safety margins for DVFS */
> > +
> > + if (freq < EMC_FREQ_CUTOFF_USE_140_PERCENT)
> > + bandwidth += 4 * bandwidth / 10;
> > + else if (freq < EMC_FREQ_CUTOFF_USE_130_PERCENT)
> > + bandwidth += 3 * bandwidth / 10;
> > + else
> > + bandwidth += bandwidth / 10;
> > +
> > + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> > +
> > + return clk_set_rate(dc->emc_clk, freq);
> > +}
> > +
> > static int tegra_crtc_mode_set(struct drm_crtc *crtc,
> > struct drm_display_mode *mode,
> > struct drm_display_mode *adjusted,
> > @@ -691,7 +738,11 @@ static int tegra_crtc_mode_set(struct drm_crtc
> *crtc,
> > if (err < 0)
> > dev_err(dc->dev, "failed to enable root plane\n");
> >
> > - return 0;
> > + err = tegra_dc_program_bandwidth(dc, mode, &window);
> > + if (err)
> > + dev_err(dc->dev, "failed to program the EMC clock\n");
> > +
> > + return err;
> > }
> >
> > static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> > @@ -1260,6 +1311,12 @@ static int tegra_dc_probe(struct platform_device
> *pdev)
> > if (err < 0)
> > return err;
> >
> > + dc->emc_clk = devm_clk_get(&pdev->dev, "emc");
> > + if (IS_ERR(dc->emc_clk))
> > + dc->emc_clk = NULL;
> > + else
> > + clk_prepare_enable(dc->emc_clk);
> > +
> > regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > dc->regs = devm_ioremap_resource(&pdev->dev, regs);
> > if (IS_ERR(dc->regs))
> > @@ -1312,6 +1369,8 @@ static int tegra_dc_remove(struct platform_device
> *pdev)
> > }
> >
> > clk_disable_unprepare(dc->clk);
> > + if (dc->emc_clk)
> > + clk_disable_unprepare(dc->emc_clk);
> >
> > return 0;
> > }
> > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> > index 6753598..30d91c0 100644
> > --- a/drivers/gpu/drm/tegra/drm.h
> > +++ b/drivers/gpu/drm/tegra/drm.h
> > @@ -101,6 +101,7 @@ struct tegra_dc {
> >
> > struct clk *clk;
> > struct reset_control *rst;
> > + struct clk *emc_clk;
> > void __iomem *regs;
> > int irq;
> >
>
> --
> Pengutronix e.K. | Lucas Stach |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
[-- Attachment #1.2: Type: text/html, Size: 7414 bytes --]
[-- Attachment #2: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] drm/tegra: Support setting the EMC clock
[not found] ` <CACP_E+J-sCsiiSX-apX3ZqWFHVGxgN5FG9eu9-qTjLQHF22DwA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2014-05-26 9:35 ` Thierry Reding
2014-05-26 9:52 ` Stéphane Marchesin
0 siblings, 1 reply; 8+ messages in thread
From: Thierry Reding @ 2014-05-26 9:35 UTC (permalink / raw)
To: Stéphane Marchesin
Cc: Lucas Stach, Stéphane Marchesin,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 6247 bytes --]
On Mon, May 26, 2014 at 11:28:42AM +0200, Stéphane Marchesin wrote:
>
>
>
> On Mon, May 26, 2014 at 2:07 AM, Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org<mailto:l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>> wrote:
> > Am Freitag, den 23.05.2014, 18:58 -0700 schrieb Stéphane Marchesin:
> > > The current code doesn't enable the EMC clock, without which the
> > > display cannot function, so let's enable this clock. We also need a
> > > bit of code to pick the right frequency for the EMC clock depending
> > > on the current video mode settings.
> > >
> > That's not the right way to do it. The DRM driver has no business
> > controlling the EMC clock directly. This should be done through a real
> > EMC driver plus some kind of bus QoS, where DC is just one client.
>
> I thought about it but didn't see another consumer in upstream
> kernels. Who are the other consumers of EMC?
There are no other EMC consumers upstream at the moment. Some recent
discussions also indicate that it's unlikely that EMC scaling will be
implemented using shared clocks upstream.
See here for the full description:
https://lkml.org/lkml/2014/5/13/469
Also adding linux-tegra to Cc. I like to keep that list in the loop for
patches that touch the Tegra DRM driver. That's especially useful if
other APIs are involved (such as clocks here).
Thierry
>
> Stéphane
>
>
> Regards,
> Lucas
>
> > Signed-off-by: Stéphane Marchesin <marcheu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org<mailto:marcheu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>>
> > ---
> > drivers/gpu/drm/tegra/dc.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-
> > drivers/gpu/drm/tegra/drm.h | 1 +
> > 2 files changed, 61 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> > index edb871d..f398dfb 100644
> > --- a/drivers/gpu/drm/tegra/dc.c
> > +++ b/drivers/gpu/drm/tegra/dc.c
> > @@ -325,6 +325,9 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
> > }
> >
> > drm_vblank_off(drm, dc->pipe);
> > +
> > + if (dc->emc_clk)
> > + clk_set_rate(dc->emc_clk, 0);
> > }
> >
> > static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
> > @@ -640,6 +643,50 @@ unsigned int tegra_dc_format(uint32_t format)
> > return WIN_COLOR_DEPTH_B8G8R8A8;
> > }
> >
> > +static unsigned long tegra_emc_bw_to_freq_req(unsigned long bw)
> > +{
> > + int bytes_per_emc_clock;
> > +
> > + if (of_machine_is_compatible("nvidia,tegra124"))
> > + bytes_per_emc_clock = 16;
> > + else
> > + bytes_per_emc_clock = 8;
> > +
> > + return (bw + bytes_per_emc_clock - 1) / bytes_per_emc_clock;
> > +}
> > +
> > +#define EMC_FREQ_CUTOFF_USE_130_PERCENT 100000000UL
> > +#define EMC_FREQ_CUTOFF_USE_140_PERCENT 50000000UL
> > +
> > +static int tegra_dc_program_bandwidth(struct tegra_dc *dc,
> > + struct drm_display_mode *mode,
> > + struct tegra_dc_window *window)
> > +{
> > + unsigned long bandwidth = mode->clock * window->bits_per_pixel / 8;
> > + unsigned long freq;
> > + struct clk *emc_master;
> > +
> > + if (!dc->emc_clk)
> > + return 0;
> > +
> > + emc_master = clk_get_parent(dc->emc_clk);
> > + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> > + freq = clk_round_rate(emc_master, freq);
> > +
> > + /* XXX: Add safety margins for DVFS */
> > +
> > + if (freq < EMC_FREQ_CUTOFF_USE_140_PERCENT)
> > + bandwidth += 4 * bandwidth / 10;
> > + else if (freq < EMC_FREQ_CUTOFF_USE_130_PERCENT)
> > + bandwidth += 3 * bandwidth / 10;
> > + else
> > + bandwidth += bandwidth / 10;
> > +
> > + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> > +
> > + return clk_set_rate(dc->emc_clk, freq);
> > +}
> > +
> > static int tegra_crtc_mode_set(struct drm_crtc *crtc,
> > struct drm_display_mode *mode,
> > struct drm_display_mode *adjusted,
> > @@ -691,7 +738,11 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
> > if (err < 0)
> > dev_err(dc->dev, "failed to enable root plane\n");
> >
> > - return 0;
> > + err = tegra_dc_program_bandwidth(dc, mode, &window);
> > + if (err)
> > + dev_err(dc->dev, "failed to program the EMC clock\n");
> > +
> > + return err;
> > }
> >
> > static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> > @@ -1260,6 +1311,12 @@ static int tegra_dc_probe(struct platform_device *pdev)
> > if (err < 0)
> > return err;
> >
> > + dc->emc_clk = devm_clk_get(&pdev->dev, "emc");
> > + if (IS_ERR(dc->emc_clk))
> > + dc->emc_clk = NULL;
> > + else
> > + clk_prepare_enable(dc->emc_clk);
> > +
> > regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > dc->regs = devm_ioremap_resource(&pdev->dev, regs);
> > if (IS_ERR(dc->regs))
> > @@ -1312,6 +1369,8 @@ static int tegra_dc_remove(struct platform_device *pdev)
> > }
> >
> > clk_disable_unprepare(dc->clk);
> > + if (dc->emc_clk)
> > + clk_disable_unprepare(dc->emc_clk);
> >
> > return 0;
> > }
> > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> > index 6753598..30d91c0 100644
> > --- a/drivers/gpu/drm/tegra/drm.h
> > +++ b/drivers/gpu/drm/tegra/drm.h
> > @@ -101,6 +101,7 @@ struct tegra_dc {
> >
> > struct clk *clk;
> > struct reset_control *rst;
> > + struct clk *emc_clk;
> > void __iomem *regs;
> > int irq;
> >
>
> --
> Pengutronix e.K. | Lucas Stach |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
>
> _______________________________________________
> dri-devel mailing list
> dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org<mailto:dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] drm/tegra: Support setting the EMC clock
2014-05-26 9:35 ` Thierry Reding
@ 2014-05-26 9:52 ` Stéphane Marchesin
0 siblings, 0 replies; 8+ messages in thread
From: Stéphane Marchesin @ 2014-05-26 9:52 UTC (permalink / raw)
To: Thierry Reding
Cc: linux-tegra@vger.kernel.org, Stéphane Marchesin,
dri-devel@lists.freedesktop.org
[-- Attachment #1.1: Type: text/plain, Size: 6711 bytes --]
On Mon, May 26, 2014 at 2:35 AM, Thierry Reding <treding@nvidia.com> wrote:
> On Mon, May 26, 2014 at 11:28:42AM +0200, Stéphane Marchesin wrote:
> >
> >
> >
> > On Mon, May 26, 2014 at 2:07 AM, Lucas Stach <l.stach@pengutronix.de
> <mailto:l.stach@pengutronix.de>> wrote:
> > > Am Freitag, den 23.05.2014, 18:58 -0700 schrieb Stéphane Marchesin:
> > > > The current code doesn't enable the EMC clock, without which the
> > > > display cannot function, so let's enable this clock. We also need a
> > > > bit of code to pick the right frequency for the EMC clock depending
> > > > on the current video mode settings.
> > > >
> > > That's not the right way to do it. The DRM driver has no business
> > > controlling the EMC clock directly. This should be done through a real
> > > EMC driver plus some kind of bus QoS, where DC is just one client.
> >
> > I thought about it but didn't see another consumer in upstream
> > kernels. Who are the other consumers of EMC?
>
> There are no other EMC consumers upstream at the moment. Some recent
> discussions also indicate that it's unlikely that EMC scaling will be
> implemented using shared clocks upstream.
>
> See here for the full description:
>
> https://lkml.org/lkml/2014/5/13/469
So if keeping the EMC clock private is a no-go, and shared clocks are also
a no-go, should I just make a separate one-off driver just for EMC and call
into that?
Stéphane
>
>
> Also adding linux-tegra to Cc. I like to keep that list in the loop for
> patches that touch the Tegra DRM driver. That's especially useful if
> other APIs are involved (such as clocks here).
>
> Thierry
>
> >
> > Stéphane
> >
> >
> > Regards,
> > Lucas
> >
> > > Signed-off-by: Stéphane Marchesin <marcheu@chromium.org<mailto:
> marcheu@chromium.org>>
> > > ---
> > > drivers/gpu/drm/tegra/dc.c | 61
> ++++++++++++++++++++++++++++++++++++++++++++-
> > > drivers/gpu/drm/tegra/drm.h | 1 +
> > > 2 files changed, 61 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> > > index edb871d..f398dfb 100644
> > > --- a/drivers/gpu/drm/tegra/dc.c
> > > +++ b/drivers/gpu/drm/tegra/dc.c
> > > @@ -325,6 +325,9 @@ static void tegra_crtc_disable(struct drm_crtc
> *crtc)
> > > }
> > >
> > > drm_vblank_off(drm, dc->pipe);
> > > +
> > > + if (dc->emc_clk)
> > > + clk_set_rate(dc->emc_clk, 0);
> > > }
> > >
> > > static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
> > > @@ -640,6 +643,50 @@ unsigned int tegra_dc_format(uint32_t format)
> > > return WIN_COLOR_DEPTH_B8G8R8A8;
> > > }
> > >
> > > +static unsigned long tegra_emc_bw_to_freq_req(unsigned long bw)
> > > +{
> > > + int bytes_per_emc_clock;
> > > +
> > > + if (of_machine_is_compatible("nvidia,tegra124"))
> > > + bytes_per_emc_clock = 16;
> > > + else
> > > + bytes_per_emc_clock = 8;
> > > +
> > > + return (bw + bytes_per_emc_clock - 1) / bytes_per_emc_clock;
> > > +}
> > > +
> > > +#define EMC_FREQ_CUTOFF_USE_130_PERCENT 100000000UL
> > > +#define EMC_FREQ_CUTOFF_USE_140_PERCENT 50000000UL
> > > +
> > > +static int tegra_dc_program_bandwidth(struct tegra_dc *dc,
> > > + struct drm_display_mode *mode,
> > > + struct tegra_dc_window *window)
> > > +{
> > > + unsigned long bandwidth = mode->clock * window->bits_per_pixel /
> 8;
> > > + unsigned long freq;
> > > + struct clk *emc_master;
> > > +
> > > + if (!dc->emc_clk)
> > > + return 0;
> > > +
> > > + emc_master = clk_get_parent(dc->emc_clk);
> > > + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> > > + freq = clk_round_rate(emc_master, freq);
> > > +
> > > + /* XXX: Add safety margins for DVFS */
> > > +
> > > + if (freq < EMC_FREQ_CUTOFF_USE_140_PERCENT)
> > > + bandwidth += 4 * bandwidth / 10;
> > > + else if (freq < EMC_FREQ_CUTOFF_USE_130_PERCENT)
> > > + bandwidth += 3 * bandwidth / 10;
> > > + else
> > > + bandwidth += bandwidth / 10;
> > > +
> > > + freq = tegra_emc_bw_to_freq_req(bandwidth) * 1000;
> > > +
> > > + return clk_set_rate(dc->emc_clk, freq);
> > > +}
> > > +
> > > static int tegra_crtc_mode_set(struct drm_crtc *crtc,
> > > struct drm_display_mode *mode,
> > > struct drm_display_mode *adjusted,
> > > @@ -691,7 +738,11 @@ static int tegra_crtc_mode_set(struct drm_crtc
> *crtc,
> > > if (err < 0)
> > > dev_err(dc->dev, "failed to enable root plane\n");
> > >
> > > - return 0;
> > > + err = tegra_dc_program_bandwidth(dc, mode, &window);
> > > + if (err)
> > > + dev_err(dc->dev, "failed to program the EMC clock\n");
> > > +
> > > + return err;
> > > }
> > >
> > > static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int
> y,
> > > @@ -1260,6 +1311,12 @@ static int tegra_dc_probe(struct
> platform_device *pdev)
> > > if (err < 0)
> > > return err;
> > >
> > > + dc->emc_clk = devm_clk_get(&pdev->dev, "emc");
> > > + if (IS_ERR(dc->emc_clk))
> > > + dc->emc_clk = NULL;
> > > + else
> > > + clk_prepare_enable(dc->emc_clk);
> > > +
> > > regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > dc->regs = devm_ioremap_resource(&pdev->dev, regs);
> > > if (IS_ERR(dc->regs))
> > > @@ -1312,6 +1369,8 @@ static int tegra_dc_remove(struct
> platform_device *pdev)
> > > }
> > >
> > > clk_disable_unprepare(dc->clk);
> > > + if (dc->emc_clk)
> > > + clk_disable_unprepare(dc->emc_clk);
> > >
> > > return 0;
> > > }
> > > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> > > index 6753598..30d91c0 100644
> > > --- a/drivers/gpu/drm/tegra/drm.h
> > > +++ b/drivers/gpu/drm/tegra/drm.h
> > > @@ -101,6 +101,7 @@ struct tegra_dc {
> > >
> > > struct clk *clk;
> > > struct reset_control *rst;
> > > + struct clk *emc_clk;
> > > void __iomem *regs;
> > > int irq;
> > >
> >
> > --
> > Pengutronix e.K. | Lucas Stach |
> > Industrial Linux Solutions | http://www.pengutronix.de/ |
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org<mailto:dri-devel@lists.freedesktop.org>
> > http://lists.freedesktop.org/mailman/listinfo/dri-devel
> >
>
[-- Attachment #1.2: Type: text/html, Size: 9338 bytes --]
[-- Attachment #2: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] drm/tegra: Align FB pitch
2014-05-24 1:58 [PATCH 1/3] drm/tegra: Align FB pitch Stéphane Marchesin
2014-05-24 1:58 ` [PATCH 2/3] drm/tegra: Support setting the EMC clock Stéphane Marchesin
2014-05-24 1:58 ` [PATCH 3/3] drm/tegra: Don't hardcode link parameters Stéphane Marchesin
@ 2014-06-05 9:40 ` Thierry Reding
2 siblings, 0 replies; 8+ messages in thread
From: Thierry Reding @ 2014-06-05 9:40 UTC (permalink / raw)
To: Stéphane Marchesin; +Cc: treding, dri-devel
[-- Attachment #1.1: Type: text/plain, Size: 981 bytes --]
On Fri, May 23, 2014 at 06:58:32PM -0700, Stéphane Marchesin wrote:
> The display controller doesn't handle non-256 byte aligned buffer
> pitches. If you give it an unaligned buffer, it will stop after the
> first line and will report underflows in the debug registers
> (DC_WINBUF_UFLOW_STATUS and friends). So let's make sure that all our
> framebuffer pitches are 256-byte aligned.
>
> Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
> ---
> drivers/gpu/drm/tegra/drm.h | 2 ++
> drivers/gpu/drm/tegra/fb.c | 3 ++-
> drivers/gpu/drm/tegra/gem.c | 2 ++
> 3 files changed, 6 insertions(+), 1 deletion(-)
Can you point me to where this requirement is documented? I've gone
through the TRM and all I can find is that the line stride needs to be
64 byte aligned. Also I seem to remember that resolutions such as
1366x768 used to work for HDMI at least on earlier Tegra generations.
Perhaps this is a requirement that's new on Tegra124?
Thierry
[-- Attachment #1.2: Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-06-05 9:43 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-24 1:58 [PATCH 1/3] drm/tegra: Align FB pitch Stéphane Marchesin
2014-05-24 1:58 ` [PATCH 2/3] drm/tegra: Support setting the EMC clock Stéphane Marchesin
2014-05-26 9:07 ` Lucas Stach
2014-05-26 9:28 ` Stéphane Marchesin
[not found] ` <CACP_E+J-sCsiiSX-apX3ZqWFHVGxgN5FG9eu9-qTjLQHF22DwA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-05-26 9:35 ` Thierry Reding
2014-05-26 9:52 ` Stéphane Marchesin
2014-05-24 1:58 ` [PATCH 3/3] drm/tegra: Don't hardcode link parameters Stéphane Marchesin
2014-06-05 9:40 ` [PATCH 1/3] drm/tegra: Align FB pitch Thierry Reding
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.