* [PATCH 1/3] i2c: bcm2835: Fix hang for writing messages larger than 16 bytes
From: Noralf Trønnes @ 2016-09-19 17:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87zin3omsa.fsf@eliezer.anholt.net>
Den 19.09.2016 18:51, skrev Eric Anholt:
> Noralf Tr?nnes <noralf@tronnes.org> writes:
>
>> Writing messages larger than the FIFO size results in a hang, rendering
>> the machine unusable. This is because the RXD status flag is set on the
>> first interrupt which results in bcm2835_drain_rxfifo() stealing bytes
>> from the buffer. The controller continues to trigger interrupts waiting
>> for the missing bytes, but bcm2835_fill_txfifo() has none to give.
>> In this situation wait_for_completion_timeout() apparently is unable to
>> stop the madness.
>>
>> The BCM2835 ARM Peripherals datasheet has this to say about the flags:
>> TXD: is set when the FIFO has space for at least one byte of data.
>> RXD: is set when the FIFO contains at least one byte of data.
>> TXW: is set during a write transfer and the FIFO is less than full.
>> RXR: is set during a read transfer and the FIFO is or more full.
>>
>> Implementing the logic from the downstream i2c-bcm2708 driver solved
>> the hang problem.
>>
>> Signed-off-by: Noralf Tr?nnes <noralf@tronnes.org>
> Patches 1, 3 are:
>
> Reviewed-by: Eric Anholt <eric@anholt.net>
>
> For patch 2 I followed some of it, but couldn't quite say it's a review.
> I trust your testing, and that the path has had a lot more testing in
> the downstream tree, so it's:
I don't know how much testing downstream really has had since this feature
is disabled by default. So there is a possibility that this can break some
devices (while at the same time enable others).
I wondered about adding a module parameter so it could be disabled at
runtime, but decided to see what the review would be first.
It is of course possible to add a this module parameter later should it
turn out to break some device.
Noralf.
> Acked-by: Eric Anholt <eric@anholt.net>
>
> Thanks!
^ permalink raw reply
* [PATCH] irqchip/gicv3: silence noisy DEBUG_PER_CPU_MAPS warning
From: James Morse @ 2016-09-19 17:29 UTC (permalink / raw)
To: linux-arm-kernel
gic_raise_softirq() walks the list of cpus using for_each_cpu(), it calls
gic_compute_target_list() which advances the iterator by the number of
CPUs in the cluster.
If gic_compute_target_list() reaches the last CPU it leaves the iterator
pointing at the last CPU. This means the next time round the for_each_cpu()
loop cpumask_next() will be called with an invalid CPU.
This triggers a warning when built with CONFIG_DEBUG_PER_CPU_MAPS:
[ 3.077738] GICv3: CPU1: found redistributor 1 region 0:0x000000002f120000
[ 3.077943] CPU1: Booted secondary processor [410fd0f0]
[ 3.078542] ------------[ cut here ]------------
[ 3.078746] WARNING: CPU: 1 PID: 0 at ../include/linux/cpumask.h:121 gic_raise_softirq+0x12c/0x170
[ 3.078812] Modules linked in:
[ 3.078869]
[ 3.078930] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.8.0-rc5+ #5188
[ 3.078994] Hardware name: Foundation-v8A (DT)
[ 3.079059] task: ffff80087a1a0080 task.stack: ffff80087a19c000
[ 3.079145] PC is at gic_raise_softirq+0x12c/0x170
[ 3.079226] LR is at gic_raise_softirq+0xa4/0x170
[ 3.079296] pc : [<ffff0000083ead24>] lr : [<ffff0000083eac9c>] pstate: 200001c9
[ 3.081139] Call trace:
[ 3.081202] Exception stack(0xffff80087a19fbe0 to 0xffff80087a19fd10)
[ 3.082269] [<ffff0000083ead24>] gic_raise_softirq+0x12c/0x170
[ 3.082354] [<ffff00000808e614>] smp_send_reschedule+0x34/0x40
[ 3.082433] [<ffff0000080e80a0>] resched_curr+0x50/0x88
[ 3.082512] [<ffff0000080e89d0>] check_preempt_curr+0x60/0xd0
[ 3.082593] [<ffff0000080e8a60>] ttwu_do_wakeup+0x20/0xe8
[ 3.082672] [<ffff0000080e8bb8>] ttwu_do_activate+0x90/0xc0
[ 3.082753] [<ffff0000080ea9a4>] try_to_wake_up+0x224/0x370
[ 3.082836] [<ffff0000080eabc8>] default_wake_function+0x10/0x18
[ 3.082920] [<ffff000008103134>] __wake_up_common+0x5c/0xa0
[ 3.083003] [<ffff0000081031f4>] __wake_up_locked+0x14/0x20
[ 3.083086] [<ffff000008103f80>] complete+0x40/0x60
[ 3.083168] [<ffff00000808df7c>] secondary_start_kernel+0x15c/0x1d0
[ 3.083240] [<00000000808911a4>] 0x808911a4
[ 3.113401] Detected PIPT I-cache on CPU2
Avoid updating the iterator if the next call to cpumask_next() would
cause the for_each_cpu() loop to exit.
There is no change to gic_raise_softirq()'s behaviour, (cpumask_next()s
eventual call to _find_next_bit() will return early as start >= nbits),
this patch just silences the warning.
Signed-off-by: James Morse <james.morse@arm.com>
---
drivers/irqchip/irq-gic-v3.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index ede5672ab34d..9e37c447cc2c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -548,6 +548,7 @@ static int gic_starting_cpu(unsigned int cpu)
static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
unsigned long cluster_id)
{
+ int next_cpu;
int cpu = *base_cpu;
unsigned long mpidr = cpu_logical_map(cpu);
u16 tlist = 0;
@@ -562,9 +563,10 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
tlist |= 1 << (mpidr & 0xf);
- cpu = cpumask_next(cpu, mask);
- if (cpu >= nr_cpu_ids)
+ next_cpu = cpumask_next(cpu, mask);
+ if (next_cpu >= nr_cpu_ids)
goto out;
+ cpu = next_cpu;
mpidr = cpu_logical_map(cpu);
--
2.8.0.rc3
^ permalink raw reply related
* [PATCH] arm: dts: fix rk3066a based boards vdd_log voltage initialization
From: Heiko Stuebner @ 2016-09-19 17:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919191327.741a2b89@bbrezillon>
Am Montag, 19. September 2016, 19:13:27 CEST schrieb Boris Brezillon:
> On Mon, 19 Sep 2016 09:38:34 -0700
>
> Doug Anderson <dianders@chromium.org> wrote:
> > Hi,
> >
> > On Mon, Sep 19, 2016 at 9:15 AM, Heiko Stuebner <heiko@sntech.de> wrote:
> > > Am Montag, 19. September 2016, 08:15:30 CEST schrieb Doug Anderson:
> > >> Hi,
> > >>
> > >> On Mon, Sep 19, 2016 at 1:44 AM, Andy Yan <andy.yan@rock-chips.com>
wrote:
> > >> > The current rk3066a based boards(Rayeager, Bqcurie2, Marsboard) use
> > >> > pwm modulate vdd_logic voltage, but the pwm is default disabled and
> > >> > the pwm pin acts as a gpio before pwm regulator probed, so the pwm
> > >> > regulator driver will get a zero dutycycle at probe time, so change
> > >> > the initial dutycycle to zero to match pwm_regulator_init_state
> > >> > check.
> > >> >
> > >> > Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
> > >> >
> > >> > ---
> > >> >
> > >> > arch/arm/boot/dts/rk3066a-bqcurie2.dts | 2 +-
> > >> > arch/arm/boot/dts/rk3066a-marsboard.dts | 2 +-
> > >> > arch/arm/boot/dts/rk3066a-rayeager.dts | 2 +-
> > >> > 3 files changed, 3 insertions(+), 3 deletions(-)
> > >> >
> > >> > diff --git a/arch/arm/boot/dts/rk3066a-bqcurie2.dts
> > >> > b/arch/arm/boot/dts/rk3066a-bqcurie2.dts index bc674ee..618450d
> > >> > 100644
> > >> > --- a/arch/arm/boot/dts/rk3066a-bqcurie2.dts
> > >> > +++ b/arch/arm/boot/dts/rk3066a-bqcurie2.dts
> > >> > @@ -61,7 +61,7 @@
> > >> >
> > >> > regulator-min-microvolt = <1200000>;
> > >> > regulator-max-microvolt = <1200000>;
> > >> > regulator-always-on;
> > >> >
> > >> > - voltage-table = <1000000 100>,
> > >> > + voltage-table = <1000000 0>,
> > >>
> > >> In my opinion this isn't quite the right answer. I think that you
> > >> should add a new property describing the voltage in the case that the
> > >>
> > >> pin is an input and you should fill that property in, like:
> > >> voltage-when-input = <1000000>;
> > >
> > > I'd think this would be more of a pwm issue, not something the
> > > pwm-regulator should need to care about.
> > >
> > > Ideally the pwm driver should be able to return some state information
> > > even if disabled? I.e. deriving a duty-cycle value from its pin state
> > > similar to what Doug described below (it's either 0% or 100%)
> > >
> > > But right now I have a hard time understanding how the pwm could return
> > > any
> > > duty-cycle information for an input gpio to the pwm-regulator, as I
> > > assume the pwm-driver has to probe (and thus set pinctrl to the pwm
> > > function) before the pwm-regulator is able to get the pwm handle?
> >
> > Hrm, right. The PWM ought to own the pinctrl, not the regulator.
> > Hrm. Then I guess this gets more complicated.
> >
> > One thing to point out, though, is that an EE I talked to said that
> > the "voltage when input" is actually a well defined property and is
> > unrelated to the min/max voltage. AKA: it's not guaranteed to be
> > equal to the 50% duty cycle. ...so adding a property to the PWM
> > regulator that includes this value is something very sane. The
> > "voltage when input" is defined by the pile of resistors and
> > capacitors that are used to actually make the PWM control the
> > regulator.
> >
> > The "voltage when input" is super important because this is the
> > voltage that's used at bootup (when all pins are configured as inputs,
> > possible with a pull applied) and that's used during suspend time when
> > the PWM stops.
>
> Correct me if I'm wrong, but the main problem here is that, when we try
> to detect the initial regulator state, we ran into a "missing entry in
> the duty-cycle <-> voltage table" error, which then triggers an -EINVAL
> error preventing the PWM regulator probe to succeed.
I'm unsure about this ... i.e. according to Andy's description, the pin is
muxed as gpio and set to input, which in turn results in the voltage-when-
input scenario.
So what happens with that voltage when the pwm-driver (= driver-core after
probe) switches the pinmux to the pwm output, but that pwm itself is not
running?
For veyrons it was easy, as the firmware set up the pwm to what it wanted, so
the state could be read back.
^ permalink raw reply
* [PATCH 00/27] drm/rockchip: MIPI fixes & improvements
From: John Keeping @ 2016-09-19 17:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
D'oh, I got send-email horribly wrong here. Please ignore the n/27
patches following this message - the n/26 versions are correct.
I won't spam the list with a cleaned-up v2 immediately, but I'll make
extra sure to clean out my working directory when I do send the re-roll!
On Mon, 19 Sep 2016 18:17:10 +0100, John Keeping wrote:
> This is a bit of a mixed selection of patches to all areas of the
> Rockchip dw-mipi-dsi driver, which I've been using for a while.
>
> The first few patches fix the driver's use of the atomic API by removing
> hardware manipulation from the mode_set hook:
>
> drm/rockchip: dw-mipi-dsi: use mode from display state
> drm/rockchip: dw-mipi-dsi: pass new mode into MIPI mode set
> drm/rockchip: dw-mipi-dsi: don't configure hardware in mode_set for
> MIPI
> drm/rockchip: dw-mipi-dsi: rename commit hook to enable
>
> The following several patches fix various aspects of DSI host transfers
> in order to improve support for displays that need to be set up via DSI
> commands:
>
> drm/rockchip: dw-mipi-dsi: fix command header writes
> drm/rockchip: dw-mipi-dsi: fix generic packet status check
> drm/rockchip: dw-mipi-dsi: avoid out-of-bounds read on tx_buf
> drm/rockchip: dw-mipi-dsi: include bad value in error message
> drm/rockchip: dw-mipi-dsi: respect message flags
> drm/rockchip: dw-mipi-dsi: only request HS clock when required
> drm/rockchip: dw-mipi-dsi: don't assume buffer is aligned
> drm/rockchip: dw-mipi-dsi: prepare panel after phy init
> drm/rockchip: dw-mipi-dsi: allow commands in panel_disable
>
> Then a bunch of patches to improve the PHY PLL and other clock setup:
>
> drm/rockchip: dw-mipi-dsi: fix escape clock rate
> drm/rockchip: dw-mipi-dsi: ensure PHY is reset
> drm/rockchip: dw-mipi-dsi: configure bias and bandgap before enable
> drm/rockchip: dw-mipi-dsi: don't enable PHY PLL until it's configured
> drm/rockchip: dw-mipi-dsi: properly configure PHY timing
> drm/rockchip: dw-mipi-dsi: improve PLL configuration
>
> A couple of patches make the VOP and MIPI host consistent when panels do
> not set explicit hsync/vsync polarities:
>
> drm/rockchip: dw-mipi-dsi: use positive check for N{H,V}SYNC
> drm/rockchip: vop: test for P{H,V}SYNC
>
> The following patch fixes fbcon by making sure that the output
> resolution is known before it loads:
>
> drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
>
> Then a patch that should be self-explanatory:
>
> drm/rockchip: dw-mipi-dsi: support non-burst modes
>
> And the final two patches were useful in development but aren't really
> needed once everything's working:
>
> drm/rockchip: dw-mipi-dsi: add reset control
> drm/rockchip: dw-mipi-dsi: support read commands
>
>
> John Keeping (26):
> drm/rockchip: dw-mipi-dsi: use mode from display state
> drm/rockchip: dw-mipi-dsi: pass new mode into MIPI mode set
> drm/rockchip: dw-mipi-dsi: don't configure hardware in mode_set for
> MIPI
> drm/rockchip: dw-mipi-dsi: rename commit hook to enable
> drm/rockchip: dw-mipi-dsi: fix command header writes
> drm/rockchip: dw-mipi-dsi: fix generic packet status check
> drm/rockchip: dw-mipi-dsi: avoid out-of-bounds read on tx_buf
> drm/rockchip: dw-mipi-dsi: include bad value in error message
> drm/rockchip: dw-mipi-dsi: respect message flags
> drm/rockchip: dw-mipi-dsi: only request HS clock when required
> drm/rockchip: dw-mipi-dsi: don't assume buffer is aligned
> drm/rockchip: dw-mipi-dsi: prepare panel after phy init
> drm/rockchip: dw-mipi-dsi: allow commands in panel_disable
> drm/rockchip: dw-mipi-dsi: fix escape clock rate
> drm/rockchip: dw-mipi-dsi: ensure PHY is reset
> drm/rockchip: dw-mipi-dsi: configure bias and bandgap before enable
> drm/rockchip: dw-mipi-dsi: don't enable PHY PLL until it's configured
> drm/rockchip: dw-mipi-dsi: properly configure PHY timing
> drm/rockchip: dw-mipi-dsi: improve PLL configuration
> drm/rockchip: dw-mipi-dsi: use specific poll helper
> drm/rockchip: dw-mipi-dsi: use positive check for N{H,V}SYNC
> drm/rockchip: vop: test for P{H,V}SYNC
> drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
> drm/rockchip: dw-mipi-dsi: support non-burst modes
> drm/rockchip: dw-mipi-dsi: add reset control
> drm/rockchip: dw-mipi-dsi: support read commands
>
> drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 325 ++++++++++++++++++++--------
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 +-
> 2 files changed, 234 insertions(+), 95 deletions(-)
>
^ permalink raw reply
* [PATCH] arm: dts: fix rk3066a based boards vdd_log voltage initialization
From: Doug Anderson @ 2016-09-19 17:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919191327.741a2b89@bbrezillon>
Hi,
On Mon, Sep 19, 2016 at 10:13 AM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> Correct me if I'm wrong, but the main problem here is that, when we try
> to detect the initial regulator state, we ran into a "missing entry in
> the duty-cycle <-> voltage table" error, which then triggers an -EINVAL
> error preventing the PWM regulator probe to succeed.
>
> Of course, adding an entry for the 0% dutycle case would solve the
> issue, but I wonder if we should not allow "unknown value" at probe
> time, and let the regulator user set the voltage output when it claims
> it.
>
> Another option would be to fake a valid value in this case (choose the
> closest entry in the voltage table?).
If the goal is to avoid glitching the voltage at bootup, then the
above doesn't really solve it.
For instance, you could have:
0% - 1.5V
100% - 0.8V
When configured as input: 1.1V
Max useful value: 1.2V
So if firmware doesn't touch the PWM regulator then that means you're
booting up at 1.1V.
If you read out the PWM itself, it will claim that it's running at 0%.
While that's true, that doesn't mean that the voltage on the system is
actually 1.5V because at boot the system had configured the pinmux as
GPIO input. ...so it's actually 1.1V because the PWM isn't actually
controlling the pins.
So if you want to avoid glitching the line then you want to make sure
that you properly init to 1.1V, _not_ to 1.5V.
In the case above, it's possible that 1.5V isn't really so great for
the hardware lifespan because 1.2V is the maximum useful value. You
could argue that the hardware is badly designed in this case, but I
have certainly seen boards designed where the maximum achievable value
is higher than the maximum "safe" value.
-Doug
^ permalink raw reply
* [PATCH 26/26] drm/rockchip: dw-mipi-dsi: support read commands
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
I haven't found any method for getting the length of a response, so this
just uses the requested rx_len
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 54 ++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index d0b2f6e9517d..6dc43c024bca 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -676,6 +676,54 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
return dw_mipi_dsi_gen_pkt_hdr_write(dsi, hdr_val);
}
+static int dw_mipi_dsi_dcs_read(struct dw_mipi_dsi *dsi,
+ const struct mipi_dsi_msg *msg)
+{
+ const u8 *tx_buf = msg->tx_buf;
+ u8 *rx_buf = msg->rx_buf;
+ size_t i;
+ int ret, val;
+
+ dsi_write(dsi, DSI_PCKHDL_CFG, EN_CRC_RX | EN_ECC_RX | EN_BTA);
+ dsi_write(dsi, DSI_GEN_HDR, GEN_HDATA(tx_buf[0]) | GEN_HTYPE(msg->type));
+
+ ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
+ val, !(val & GEN_RD_CMD_BUSY), 1000,
+ CMD_PKT_STATUS_TIMEOUT_US);
+ if (ret < 0) {
+ dev_err(dsi->dev, "failed to read command response\n");
+ return ret;
+ }
+
+ for (i = 0; i < msg->rx_len;) {
+ u32 pld = dsi_read(dsi, DSI_GEN_PLD_DATA);
+ while (i < msg->rx_len) {
+ rx_buf[i] = pld & 0xff;
+ pld >>= 8;
+ i++;
+ }
+ }
+
+ return msg->rx_len;
+}
+
+static int dw_mipi_dsi_set_max_return_packet_size(struct dw_mipi_dsi *dsi,
+ size_t len)
+{
+ u8 val[] = { len & 0xff, (len >> 8) & 0xff };
+ struct mipi_dsi_msg msg = {
+ .channel = dsi->channel,
+ .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
+ .tx_buf = val,
+ .tx_len = 2,
+ };
+
+ if (len > 0xffff)
+ return -EINVAL;
+
+ return dw_mipi_dsi_dcs_short_write(dsi, &msg);
+}
+
static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
@@ -693,6 +741,12 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
case MIPI_DSI_DCS_LONG_WRITE:
ret = dw_mipi_dsi_dcs_long_write(dsi, msg);
break;
+ case MIPI_DSI_DCS_READ:
+ ret = dw_mipi_dsi_set_max_return_packet_size(dsi, msg->rx_len);
+ if (ret < 0)
+ return ret;
+ ret = dw_mipi_dsi_dcs_read(dsi, msg);
+ break;
default:
dev_err(dsi->dev, "unsupported message type 0x%02x\n",
msg->type);
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 25/26] drm/rockchip: dw-mipi-dsi: add reset control
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
In order to fully reset the state of the MIPI controller we must assert
this reset.
This is slightly more complicated than it could be in order to maintain
compatibility with device trees that do not specify the reset property.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index d93e620adea6..d0b2f6e9517d 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/mfd/syscon.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
@@ -1134,6 +1135,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
of_match_device(dw_mipi_dsi_dt_ids, dev);
const struct dw_mipi_dsi_plat_data *pdata = of_id->data;
struct platform_device *pdev = to_platform_device(dev);
+ struct reset_control *apb_rst;
struct drm_device *drm = data;
struct dw_mipi_dsi *dsi;
struct resource *res;
@@ -1172,6 +1174,34 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
return ret;
}
+ /*
+ * Note that the reset was not defined in the initial device tree, so
+ * we have to be prepared for it not being found.
+ */
+ apb_rst = devm_reset_control_get(dev, "apb");
+ if (IS_ERR(apb_rst)) {
+ if (PTR_ERR(apb_rst) == -ENODEV) {
+ apb_rst = NULL;
+ } else {
+ dev_err(dev, "Unable to get reset control: %d\n", ret);
+ return PTR_ERR(apb_rst);
+ }
+ }
+
+ if (apb_rst) {
+ ret = clk_prepare_enable(dsi->pclk);
+ if (ret) {
+ dev_err(dev, "%s: Failed to enable pclk\n", __func__);
+ return ret;
+ }
+
+ reset_control_assert(apb_rst);
+ usleep_range(10, 20);
+ reset_control_deassert(apb_rst);
+
+ clk_disable_unprepare(dsi->pclk);
+ }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 24/27] drm/rockchip: vop: test for P{H,V}SYNC
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
When connected to the MIPI DSI output, we need to use N{H,V}SYNC for the
internal connection but these flags are meaningless for DSI panels.
Switch the test so that we do not set the P{H,V}SYNC bits unless the
mode requires it.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index d486049f9722..7c4ce1b2e694 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1030,8 +1030,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
}
pin_pol = 0x8;
- pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
- pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
+ pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0;
+ pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ? (1 << 1) : 0;
VOP_CTRL_SET(vop, pin_pol, pin_pol);
switch (s->output_type) {
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 24/26] drm/rockchip: dw-mipi-dsi: support non-burst modes
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 5ecb03c24c2f..d93e620adea6 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -82,6 +82,7 @@
#define FRAME_BTA_ACK BIT(14)
#define ENABLE_LOW_POWER (0x3f << 8)
#define ENABLE_LOW_POWER_MASK (0x3f << 8)
+#define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS 0x1
#define VID_MODE_TYPE_BURST_SYNC_PULSES 0x2
#define VID_MODE_TYPE_MASK 0x3
@@ -286,6 +287,7 @@ struct dw_mipi_dsi {
u32 format;
u16 input_div;
u16 feedback_div;
+ unsigned long mode_flags;
const struct dw_mipi_dsi_plat_data *pdata;
};
@@ -549,15 +551,10 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
return -EINVAL;
}
- if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) ||
- !(device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) {
- dev_err(dsi->dev, "device mode is unsupported\n");
- return -EINVAL;
- }
-
dsi->lanes = device->lanes;
dsi->channel = device->channel;
dsi->format = device->format;
+ dsi->mode_flags = device->mode_flags;
dsi->panel = of_drm_find_panel(device->dev.of_node);
if (dsi->panel)
return drm_panel_attach(dsi->panel, &dsi->connector);
@@ -714,7 +711,12 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
{
u32 val;
- val = VID_MODE_TYPE_BURST_SYNC_PULSES | ENABLE_LOW_POWER;
+ val = ENABLE_LOW_POWER;
+
+ if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ val |= VID_MODE_TYPE_BURST_SYNC_PULSES;
+ else if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
+ val |= VID_MODE_TYPE_NON_BURST_SYNC_EVENTS;
dsi_write(dsi, DSI_VID_MODE_CFG, val);
}
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 23/27] drm/rockchip: dw-mipi-dsi: support non-burst modes
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 5ecb03c24c2f..d93e620adea6 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -82,6 +82,7 @@
#define FRAME_BTA_ACK BIT(14)
#define ENABLE_LOW_POWER (0x3f << 8)
#define ENABLE_LOW_POWER_MASK (0x3f << 8)
+#define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS 0x1
#define VID_MODE_TYPE_BURST_SYNC_PULSES 0x2
#define VID_MODE_TYPE_MASK 0x3
@@ -286,6 +287,7 @@ struct dw_mipi_dsi {
u32 format;
u16 input_div;
u16 feedback_div;
+ unsigned long mode_flags;
const struct dw_mipi_dsi_plat_data *pdata;
};
@@ -549,15 +551,10 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
return -EINVAL;
}
- if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) ||
- !(device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) {
- dev_err(dsi->dev, "device mode is unsupported\n");
- return -EINVAL;
- }
-
dsi->lanes = device->lanes;
dsi->channel = device->channel;
dsi->format = device->format;
+ dsi->mode_flags = device->mode_flags;
dsi->panel = of_drm_find_panel(device->dev.of_node);
if (dsi->panel)
return drm_panel_attach(dsi->panel, &dsi->connector);
@@ -714,7 +711,12 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
{
u32 val;
- val = VID_MODE_TYPE_BURST_SYNC_PULSES | ENABLE_LOW_POWER;
+ val = ENABLE_LOW_POWER;
+
+ if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ val |= VID_MODE_TYPE_BURST_SYNC_PULSES;
+ else if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
+ val |= VID_MODE_TYPE_NON_BURST_SYNC_EVENTS;
dsi_write(dsi, DSI_VID_MODE_CFG, val);
}
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 23/26] drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
This ensures that the output resolution is known before fbcon loads.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 2b26a54972da..5ecb03c24c2f 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1186,10 +1186,17 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
dsi->dsi_host.dev = dev;
- return mipi_dsi_host_register(&dsi->dsi_host);
+ ret = mipi_dsi_host_register(&dsi->dsi_host);
+ if (!ret && !dsi->panel) {
+ mipi_dsi_host_unregister(&dsi->dsi_host);
+ drm_encoder_cleanup(&dsi->encoder);
+ drm_connector_cleanup(&dsi->connector);
+ ret = -EPROBE_DEFER;
+ }
err_pllref:
- clk_disable_unprepare(dsi->pllref_clk);
+ if (ret)
+ clk_disable_unprepare(dsi->pllref_clk);
return ret;
}
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 22/26] drm/rockchip: vop: test for P{H,V}SYNC
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
When connected to the MIPI DSI output, we need to use N{H,V}SYNC for the
internal connection but these flags are meaningless for DSI panels.
Switch the test so that we do not set the P{H,V}SYNC bits unless the
mode requires it.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index d486049f9722..7c4ce1b2e694 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1030,8 +1030,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
}
pin_pol = 0x8;
- pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
- pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
+ pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0;
+ pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ? (1 << 1) : 0;
VOP_CTRL_SET(vop, pin_pol, pin_pol);
switch (s->output_type) {
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 22/27] drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
This ensures that the output resolution is known before fbcon loads.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 2b26a54972da..5ecb03c24c2f 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1186,10 +1186,17 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
dsi->dsi_host.dev = dev;
- return mipi_dsi_host_register(&dsi->dsi_host);
+ ret = mipi_dsi_host_register(&dsi->dsi_host);
+ if (!ret && !dsi->panel) {
+ mipi_dsi_host_unregister(&dsi->dsi_host);
+ drm_encoder_cleanup(&dsi->encoder);
+ drm_connector_cleanup(&dsi->connector);
+ ret = -EPROBE_DEFER;
+ }
err_pllref:
- clk_disable_unprepare(dsi->pllref_clk);
+ if (ret)
+ clk_disable_unprepare(dsi->pllref_clk);
return ret;
}
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 21/26] drm/rockchip: dw-mipi-dsi: use positive check for N{H, V}SYNC
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
This matches other drivers.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index ae7c330cb7ac..2b26a54972da 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -772,9 +772,9 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi)
break;
}
- if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
val |= VSYNC_ACTIVE_LOW;
- if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
val |= HSYNC_ACTIVE_LOW;
dsi_write(dsi, DSI_DPI_VCID, DPI_VID(dsi->channel));
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 21/27] drm/rockchip: dw-mipi-dsi: improve PLL configuration
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
The multiplication ratio for the PLL is required to be even due to the
use of a "by 2 pre-scaler". Currently we are likely to end up with an
odd multiplier even though there is an equivalent set of parameters with
an even multiplier.
For example, using the 324MHz bit rate with a reference clock of 24MHz
we end up with M = 27, N = 2 whereas the example in the PHY databook
gives M = 54, N = 4 for this bit rate and reference clock.
By walking down through the available multiplier instead of up we are
more likely to hit an even multiplier. With the above example we do now
get M = 54, N = 4 as given by the databook.
While doing this, change the loop limits to encode the actual limits on
the divisor, which are:
40MHz >= (pllref / N) >= 5MHz
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 911ddcbab00d..2b26a54972da 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -520,7 +520,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi,
pllref = DIV_ROUND_UP(clk_get_rate(dsi->pllref_clk), USEC_PER_SEC);
tmp = pllref;
- for (i = 1; i < 6; i++) {
+ for (i = pllref / 5; i > (pllref / 40); i--) {
pre = pllref / i;
if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
tmp = target_mbps % pre;
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 20/26] drm/rockchip: dw-mipi-dsi: use specific poll helper
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
As the documentation for readx_poll_timeout says, we want to use the
specialized macro for readl rather than using the generic version
directly.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 7983b2749518..ae7c330cb7ac 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -472,14 +472,14 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
PHY_UNRSTZ | PHY_UNSHUTDOWNZ);
- ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS,
+ ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS,
val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US);
if (ret < 0) {
dev_err(dsi->dev, "failed to wait for phy lock state\n");
return ret;
}
- ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS,
+ ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS,
val, val & STOP_STATE_CLK_LANE, 1000,
PHY_STATUS_TIMEOUT_US);
if (ret < 0) {
@@ -595,7 +595,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
int ret;
u32 val, mask;
- ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+ ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
val, !(val & GEN_CMD_FULL), 1000,
CMD_PKT_STATUS_TIMEOUT_US);
if (ret < 0) {
@@ -606,7 +606,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
dsi_write(dsi, DSI_GEN_HDR, hdr_val);
mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY;
- ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+ ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
val, (val & mask) == mask,
1000, CMD_PKT_STATUS_TIMEOUT_US);
if (ret < 0) {
@@ -665,7 +665,7 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
len -= pld_data_bytes;
}
- ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+ ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
val, !(val & GEN_PLD_W_FULL), 1000,
CMD_PKT_STATUS_TIMEOUT_US);
if (ret < 0) {
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 20/27] drm/rockchip: dw-mipi-dsi: properly configure PHY timing
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
These values are specified as constant time periods but the PHY
configuration is in terms of the current lane byte clock so using
constant values guarantees that the timings will be outside the
specification with some display configurations.
Derive the necessary configuration from the byte clock in order to
ensure that the PHY configuration is correct.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 36 ++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 61cee02e5f72..911ddcbab00d 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -384,6 +384,26 @@ static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
}
+/**
+ * ns2bc - Nanoseconds to byte clock cycles
+ */
+static inline unsigned int ns2bc(struct dw_mipi_dsi *dsi, int ns)
+{
+ unsigned long byte_clk_khz = dsi->lane_mbps * MSEC_PER_SEC / 8;
+
+ return (ns * (byte_clk_khz / 1000) + 999) / 1000;
+}
+
+/**
+ * ns2ui - Nanoseconds to UI time periods
+ */
+static inline unsigned int ns2ui(struct dw_mipi_dsi *dsi, int ns)
+{
+ unsigned long byte_clk_khz = dsi->lane_mbps * MSEC_PER_SEC;
+
+ return (ns * (byte_clk_khz / 1000) + 999) / 1000;
+}
+
static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
{
int ret, testdin, vco, val;
@@ -435,10 +455,18 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
SETRD_MAX | POWER_MANAGE |
TER_RESISTORS_ON);
-
- dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | 0xf);
- dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | 0x55);
- dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | 0xa);
+ dw_mipi_dsi_phy_write(dsi, 0x60, TLP_PROGRAM_EN | ns2bc(dsi, 500));
+ dw_mipi_dsi_phy_write(dsi, 0x61, THS_PRE_PROGRAM_EN | ns2ui(dsi, 40));
+ dw_mipi_dsi_phy_write(dsi, 0x62, THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300));
+ dw_mipi_dsi_phy_write(dsi, 0x63, THS_PRE_PROGRAM_EN | ns2ui(dsi, 100));
+ dw_mipi_dsi_phy_write(dsi, 0x64, BIT(5) | ns2bc(dsi, 100));
+ dw_mipi_dsi_phy_write(dsi, 0x65, BIT(5) | (ns2bc(dsi, 60) + 7));
+
+ dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | ns2bc(dsi, 500));
+ dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 5));
+ dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2));
+ dw_mipi_dsi_phy_write(dsi, 0x73, THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8));
+ dw_mipi_dsi_phy_write(dsi, 0x74, BIT(5) | ns2bc(dsi, 100));
dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK |
PHY_UNRSTZ | PHY_UNSHUTDOWNZ);
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 19/26] drm/rockchip: dw-mipi-dsi: improve PLL configuration
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
The multiplication ratio for the PLL is required to be even due to the
use of a "by 2 pre-scaler". Currently we are likely to end up with an
odd multiplier even though there is an equivalent set of parameters with
an even multiplier.
For example, using the 324MHz bit rate with a reference clock of 24MHz
we end up with M = 27, N = 2 whereas the example in the PHY databook
gives M = 54, N = 4 for this bit rate and reference clock.
By walking down through the available multiplier instead of up we are
more likely to hit an even multiplier. With the above example we do now
get M = 54, N = 4 as given by the databook.
While doing this, change the loop limits to encode the actual limits on
the divisor, which are:
40MHz >= (pllref / N) >= 5MHz
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 55237d72f3f9..7983b2749518 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -520,7 +520,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi,
pllref = DIV_ROUND_UP(clk_get_rate(dsi->pllref_clk), USEC_PER_SEC);
tmp = pllref;
- for (i = 1; i < 6; i++) {
+ for (i = pllref / 5; i > (pllref / 40); i--) {
pre = pllref / i;
if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
tmp = target_mbps % pre;
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 19/27] drm/rockchip: dw-mipi-dsi: don't enable PHY PLL until it's configured
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 65c89367d8b2..61cee02e5f72 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -414,12 +414,12 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
dw_mipi_dsi_phy_write(dsi, 0x44, HSFREQRANGE_SEL(testdin));
- dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->input_div));
dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_LOW_SEL(dsi->feedback_div) |
LOW_PROGRAM_EN);
dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
HIGH_PROGRAM_EN);
+ dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
BIASEXTR_SEL(BIASEXTR_127_7));
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 18/26] drm/rockchip: dw-mipi-dsi: properly configure PHY timing
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
These values are specified as constant time periods but the PHY
configuration is in terms of the current lane byte clock so using
constant values guarantees that the timings will be outside the
specification with some display configurations.
Derive the necessary configuration from the byte clock in order to
ensure that the PHY configuration is correct.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 36 ++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 463e469fd1b8..55237d72f3f9 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -384,6 +384,26 @@ static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
}
+/**
+ * ns2bc - Nanoseconds to byte clock cycles
+ */
+static inline unsigned int ns2bc(struct dw_mipi_dsi *dsi, int ns)
+{
+ unsigned long byte_clk_khz = dsi->lane_mbps * MSEC_PER_SEC / 8;
+
+ return (ns * (byte_clk_khz / 1000) + 999) / 1000;
+}
+
+/**
+ * ns2ui - Nanoseconds to UI time periods
+ */
+static inline unsigned int ns2ui(struct dw_mipi_dsi *dsi, int ns)
+{
+ unsigned long byte_clk_khz = dsi->lane_mbps * MSEC_PER_SEC;
+
+ return (ns * (byte_clk_khz / 1000) + 999) / 1000;
+}
+
static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
{
int ret, testdin, vco, val;
@@ -435,10 +455,18 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
SETRD_MAX | POWER_MANAGE |
TER_RESISTORS_ON);
-
- dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | 0xf);
- dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | 0x55);
- dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | 0xa);
+ dw_mipi_dsi_phy_write(dsi, 0x60, TLP_PROGRAM_EN | ns2bc(dsi, 500));
+ dw_mipi_dsi_phy_write(dsi, 0x61, THS_PRE_PROGRAM_EN | ns2ui(dsi, 40));
+ dw_mipi_dsi_phy_write(dsi, 0x62, THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300));
+ dw_mipi_dsi_phy_write(dsi, 0x63, THS_PRE_PROGRAM_EN | ns2ui(dsi, 100));
+ dw_mipi_dsi_phy_write(dsi, 0x64, BIT(5) | ns2bc(dsi, 100));
+ dw_mipi_dsi_phy_write(dsi, 0x65, BIT(5) | (ns2bc(dsi, 60) + 7));
+
+ dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | ns2bc(dsi, 500));
+ dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 5));
+ dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2));
+ dw_mipi_dsi_phy_write(dsi, 0x73, THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8));
+ dw_mipi_dsi_phy_write(dsi, 0x74, BIT(5) | ns2bc(dsi, 100));
dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK |
PHY_UNRSTZ | PHY_UNSHUTDOWNZ);
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 18/27] drm/rockchip: dw-mipi-dsi: configure bias and bandgap before enable
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
We should configure these functions before enabling them.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index e310c3d81bb8..65c89367d8b2 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -421,6 +421,11 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
HIGH_PROGRAM_EN);
+ dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
+ BIASEXTR_SEL(BIASEXTR_127_7));
+ dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN |
+ BANDGAP_SEL(BANDGAP_96_10));
+
dw_mipi_dsi_phy_write(dsi, 0x20, POWER_CONTROL | INTERNAL_REG_CURRENT |
BIAS_BLOCK_ON | BANDGAP_ON);
@@ -430,10 +435,6 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
SETRD_MAX | POWER_MANAGE |
TER_RESISTORS_ON);
- dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
- BIASEXTR_SEL(BIASEXTR_127_7));
- dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN |
- BANDGAP_SEL(BANDGAP_96_10));
dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | 0xf);
dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | 0x55);
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 17/27] drm/rockchip: dw-mipi-dsi: ensure PHY is reset
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
Also don't power up the DSI host at this point since this is not
necessary in order to configure the PHY and we do so later when
selecting video or command mode.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index e621b66b9617..e310c3d81bb8 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -398,7 +398,10 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
return testdin;
}
- dsi_write(dsi, DSI_PWR_UP, POWERUP);
+ /* Start by clearing PHY state */
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR);
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLR);
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR);
dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE |
VCO_RANGE_CON_SEL(vco) |
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 17/26] drm/rockchip: dw-mipi-dsi: don't enable PHY PLL until it's configured
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f824c99b872e..463e469fd1b8 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -414,12 +414,12 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
dw_mipi_dsi_phy_write(dsi, 0x44, HSFREQRANGE_SEL(testdin));
- dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->input_div));
dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_LOW_SEL(dsi->feedback_div) |
LOW_PROGRAM_EN);
dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
HIGH_PROGRAM_EN);
+ dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
BIASEXTR_SEL(BIASEXTR_127_7));
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 16/27] drm/rockchip: dw-mipi-dsi: fix escape clock rate
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
Use the same calculation as the vendor kernel to derive the escape clock
speed.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 7b4f4f150a0d..e621b66b9617 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -711,11 +711,13 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)
static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
{
+ u32 esc_clk_division = (dsi->lane_mbps >> 3) / 20 + 1;
+
dsi_write(dsi, DSI_PWR_UP, RESET);
dsi_write(dsi, DSI_PHY_RSTZ, PHY_DISFORCEPLL | PHY_DISABLECLK
| PHY_RSTZ | PHY_SHUTDOWNZ);
dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVIDSION(10) |
- TX_ESC_CLK_DIVIDSION(7));
+ TX_ESC_CLK_DIVIDSION(esc_clk_division));
}
static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi)
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
* [PATCH 16/26] drm/rockchip: dw-mipi-dsi: configure bias and bandgap before enable
From: John Keeping @ 2016-09-19 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919171747.28512-1-john@metanate.com>
We should configure these functions before enabling them.
Signed-off-by: John Keeping <john@metanate.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 73c28e205fc5..f824c99b872e 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -421,6 +421,11 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
HIGH_PROGRAM_EN);
+ dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
+ BIASEXTR_SEL(BIASEXTR_127_7));
+ dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN |
+ BANDGAP_SEL(BANDGAP_96_10));
+
dw_mipi_dsi_phy_write(dsi, 0x20, POWER_CONTROL | INTERNAL_REG_CURRENT |
BIAS_BLOCK_ON | BANDGAP_ON);
@@ -430,10 +435,6 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
SETRD_MAX | POWER_MANAGE |
TER_RESISTORS_ON);
- dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
- BIASEXTR_SEL(BIASEXTR_127_7));
- dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN |
- BANDGAP_SEL(BANDGAP_96_10));
dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | 0xf);
dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | 0x55);
--
2.10.0.278.g4f427b1.dirty
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox