* [PATCH v3] spi: spi-fsl-dspi: Add DMA support for Vybrid
From: Mark Brown @ 2016-11-11 12:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <836dd6a84fa149cafdbb0b53e792d305febf6207.1478778329.git.maitysanchayan@gmail.com>
On Thu, Nov 10, 2016 at 05:49:15PM +0530, Sanchayan Maity wrote:
A couple of small things, please send followup patches fixing them.
> + rx_word = is_double_byte_mode(dspi);
> +
> + len = rx_word ? (dma->curr_xfer_len / 2) : dma->curr_xfer_len;
Please use normal if statements, they're much easier to read.
> +err_slave_config:
> + devm_kfree(dev, dma->rx_dma_buf);
> +err_rx_dma_buf:
> + devm_kfree(dev, dma->tx_dma_buf);
You really shouldn't need to explicitly free things like this if you're
using devm_, especially in the error path from the probe function like
this where a failure is just going to result in the device failing to
instantiate so you won't have the allocation sitting around unused for
any length of time.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 455 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161111/6447812f/attachment.sig>
^ permalink raw reply
* [PATCH] staging: vc04_services: Remove explicit NULL pointer
From: Maninder Singh @ 2016-11-11 12:16 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct comparisons to NULL i.e.
'x == NULL' with '!x'
'x != NULL' with 'x'
Signed-off-by: Maninder Singh <maninder.s2@samsung.com>
---
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 32 ++++++++++----------
.../vc04_services/interface/vchiq_arm/vchiq_core.c | 4 +--
.../vc04_services/interface/vchiq_arm/vchiq_shim.c | 4 +--
.../vc04_services/interface/vchiq_arm/vchiq_util.c | 4 +--
4 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index 8fcd940..0068a1c 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -533,7 +533,7 @@ struct vchiq_io_copy_callback_context {
/* Remove all services */
i = 0;
while ((service = next_service_by_instance(instance->state,
- instance, &i)) != NULL) {
+ instance, &i))) {
status = vchiq_remove_service(service->handle);
unlock_service(service);
if (status != VCHIQ_SUCCESS)
@@ -614,7 +614,7 @@ struct vchiq_io_copy_callback_context {
&args.params, srvstate,
instance, user_service_free);
- if (service != NULL) {
+ if (service) {
user_service->service = service;
user_service->userdata = userdata;
user_service->instance = instance;
@@ -661,7 +661,7 @@ struct vchiq_io_copy_callback_context {
VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
service = find_service_for_instance(instance, handle);
- if (service != NULL) {
+ if (service) {
USER_SERVICE_T *user_service =
(USER_SERVICE_T *)service->base.userdata;
/* close_pending is false on first entry, and when the
@@ -687,7 +687,7 @@ struct vchiq_io_copy_callback_context {
VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
service = find_service_for_instance(instance, handle);
- if (service != NULL) {
+ if (service) {
USER_SERVICE_T *user_service =
(USER_SERVICE_T *)service->base.userdata;
/* close_pending is false on first entry, and when the
@@ -714,7 +714,7 @@ struct vchiq_io_copy_callback_context {
VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
service = find_service_for_instance(instance, handle);
- if (service != NULL) {
+ if (service) {
status = (cmd == VCHIQ_IOC_USE_SERVICE) ?
vchiq_use_service_internal(service) :
vchiq_release_service_internal(service);
@@ -747,7 +747,7 @@ struct vchiq_io_copy_callback_context {
service = find_service_for_instance(instance, args.handle);
- if ((service != NULL) && (args.count <= MAX_ELEMENTS)) {
+ if (service && (args.count <= MAX_ELEMENTS)) {
/* Copy elements into kernel space */
VCHIQ_ELEMENT_T elements[MAX_ELEMENTS];
if (copy_from_user(elements, args.elements,
@@ -1063,7 +1063,7 @@ struct vchiq_io_copy_callback_context {
spin_unlock(&msg_queue_spinlock);
up(&user_service->remove_event);
- if (header == NULL)
+ if (!header)
ret = -ENOTCONN;
else if (header->size <= args.bufsize) {
/* Copy to user space if msgbuf is not NULL */
@@ -1161,7 +1161,7 @@ struct vchiq_io_copy_callback_context {
VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
service = find_closed_service_for_instance(instance, handle);
- if (service != NULL) {
+ if (service) {
USER_SERVICE_T *user_service =
(USER_SERVICE_T *)service->base.userdata;
close_delivered(user_service);
@@ -1305,7 +1305,7 @@ struct vchiq_io_copy_callback_context {
/* Mark all services for termination... */
i = 0;
while ((service = next_service_by_instance(state, instance,
- &i)) != NULL) {
+ &i))) {
USER_SERVICE_T *user_service = service->base.userdata;
/* Wake the slot handler if the msg queue is full. */
@@ -1317,8 +1317,8 @@ struct vchiq_io_copy_callback_context {
/* ...and wait for them to die */
i = 0;
- while ((service = next_service_by_instance(state, instance, &i))
- != NULL) {
+ while ((service = next_service_by_instance(state,
+ instance, &i))) {
USER_SERVICE_T *user_service = service->base.userdata;
down(&service->remove_event);
@@ -1560,7 +1560,7 @@ struct vchiq_io_copy_callback_context {
num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE;
pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
- if (pages == NULL) {
+ if (!pages) {
vchiq_log_error(vchiq_arm_log_level,
"Unable to allocation memory for %d pages\n",
num_pages);
@@ -1592,7 +1592,7 @@ struct vchiq_io_copy_callback_context {
if (page_idx != prev_idx) {
- if (page != NULL)
+ if (page)
kunmap(page);
page = pages[page_idx];
kmapped_virt_ptr = kmap(page);
@@ -1610,7 +1610,7 @@ struct vchiq_io_copy_callback_context {
}
out:
- if (page != NULL)
+ if (page)
kunmap(page);
for (page_idx = 0; page_idx < num_pages; page_idx++)
@@ -2659,7 +2659,7 @@ struct vchiq_io_copy_callback_context {
int use_count = 0, i;
i = 0;
while ((service = next_service_by_instance(instance->state,
- instance, &i)) != NULL) {
+ instance, &i))) {
use_count += service->service_use_count;
unlock_service(service);
}
@@ -2685,7 +2685,7 @@ struct vchiq_io_copy_callback_context {
int i;
i = 0;
while ((service = next_service_by_instance(instance->state,
- instance, &i)) != NULL) {
+ instance, &i))) {
service->trace = trace;
unlock_service(service);
}
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 7440db2..82f6496 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -3273,7 +3273,7 @@ static const char *msg_type_str(unsigned int msg_type)
if (!service ||
(service->srvstate != VCHIQ_SRVSTATE_OPEN) ||
- ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) ||
+ ((memhandle == VCHI_MEM_HANDLE_INVALID) && (!offset)) ||
(vchiq_check_service(service) != VCHIQ_SUCCESS))
goto error_exit;
@@ -3910,7 +3910,7 @@ void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *void_mem,
}
*s++ = '\0';
- if ((label != NULL) && (*label != '\0'))
+ if (label && (*label != '\0'))
vchiq_log_trace(VCHIQ_LOG_TRACE,
"%s: %08x: %s", label, addr, line_buf);
else
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
index d977139..b6d0a75 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
@@ -639,7 +639,7 @@ int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
}
}
- return (service != NULL) ? 0 : -1;
+ return (service) ? 0 : -1;
}
EXPORT_SYMBOL(vchi_service_open);
@@ -671,7 +671,7 @@ int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle,
}
}
- return (service != NULL) ? 0 : -1;
+ return (service) ? 0 : -1;
}
EXPORT_SYMBOL(vchi_service_create);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
index 384acb8..ac6a386 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
@@ -52,7 +52,7 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
sema_init(&queue->push, 0);
queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);
- if (queue->storage == NULL) {
+ if (!queue->storage) {
vchiu_queue_delete(queue);
return 0;
}
@@ -61,7 +61,7 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
void vchiu_queue_delete(VCHIU_QUEUE_T *queue)
{
- if (queue->storage != NULL)
+ if (queue->storage)
kfree(queue->storage);
}
--
1.7.9.5
^ permalink raw reply related
* pull request: linux-firmware: Update Mediatek MT8173 VPU firmware
From: Andrew-CT Chen @ 2016-11-11 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Hi linux-firmware maintainers,
The following changes since commit a179db97914da5e650c21ba8f9b0bae04a0f8a41:
amdgpu: update SMC firmware for VI parts (2016-10-05 10:30:11 -0700)
are available in the git repository at:
https://github.com/andrewct-chen/linux_fw_vpu_v1.0.3.git v1.0.3
for you to fetch changes up to f52fd5b4f156bd1eef672d29abbdc57cf310ac1b:
mediatek: update MT8173 VPU firmware for idle state (2016-11-11 19:34:56 +0800)
----------------------------------------------------------------
Andrew-CT Chen (1):
mediatek: update MT8173 VPU firmware for idle state
vpu_d.bin | Bin 4082928 -> 4082928 bytes
vpu_p.bin | Bin 131160 -> 131160 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
^ permalink raw reply
* PM regression with LED changes in next-20161109
From: Pavel Machek @ 2016-11-11 12:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <80b645e7-c3fa-8001-d9b1-c3c8c40394fd@gmail.com>
On Thu 2016-11-10 22:34:07, Jacek Anaszewski wrote:
> Hi,
>
> On 11/10/2016 09:29 PM, Pavel Machek wrote:
> >On Thu 2016-11-10 10:55:37, Tony Lindgren wrote:
> >>* Pavel Machek <pavel@ucw.cz> [161110 09:29]:
> >>>Hi!
> >>>
> >>>>>>>Looks like commit 883d32ce3385 ("leds: core: Add support for poll()ing
> >>>>>>>the sysfs brightness attr for changes.") breaks runtime PM for me.
> >>>>>>>
> >>>>>>>On my omap dm3730 based test system, idle power consumption is over 70
> >>>>>>>times higher now with this patch! It goes from about 6mW for the core
> >>>>>>>system to over 440mW during idle meaning there's some busy timer now
> >>>>>>>active.
> >>>>>>>
> >>>>>>>Reverting this patch fixes the issue. Any ideas?
> >>>
> >>>Are you using any LED that toggles with high frequency? Like perhaps
> >>>LED that is lit when CPU is active?
> >>
> >>Yeah one of them seems to have cpu0 as the default trigger.
> >
> >Aha. Its quite obvious we don't want to notify sysfs each time that
> >one is toggled, right?
> >
> >IMO brightness should display max brightness for the trigger, as Hans
> >suggested, anything else is madness for trigger such as cpu activity.
>
> Are you suggesting that we should revert changes introduced
> by below patch?
>
> commit 29d76dfa29fe22583aefddccda0bc56aa81035dc
> Author: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
> Date: Tue Mar 18 09:47:48 2008 +0000
>
> leds: Add support to leds with readable status
>
> Some led hardware allows drivers to query the led state, and this patch
> adds a hook to let the led class take advantage of that information when
> available.
>
> Without this functionality, when access to the led hardware is not
> exclusive (i.e. firmware or hardware might change its state behind the
> kernel's back), reality goes out of sync with the led class' idea of
> what
> the led is doing, which is annoying at best.
Hmm. So userland can read the LED state, and it can get _some_ value
back, but it can not know if it is current state or not.
I don't think that's a good interface. I see it is from 2008... is
someone using it? Maybe it is too late for revert.
But I'd certainly not extend it with poll.
IMO reading/polling should only be available with some triggers. It
does not make sense with "CPU load" trigger. It makes sense with
"keyboard light changeable by hardware" trigger.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161111/cdf0fc1a/attachment.sig>
^ permalink raw reply
* [RESEND PATCH v1 02/11] dt-bindings: hisi: Add Hisilicon HiP05/06/07 Sysctrl and Djtag dts bindings
From: Anurup M @ 2016-11-11 11:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161111115346.GC11945@leverpostej>
On Friday 11 November 2016 05:23 PM, Mark Rutland wrote:
> On Fri, Nov 11, 2016 at 04:49:03PM +0530, Anurup M wrote:
>> On Thursday 10 November 2016 10:53 PM, Mark Rutland wrote:
>>> On Thu, Nov 03, 2016 at 01:41:58AM -0400, Anurup M wrote:
>>>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>>>> +Example:
>>>> + /* for Hisilicon HiP05 djtag for CPU sysctrl */
>>>> + djtag0: djtag at 80010000 {
>>>> + compatible = "hisilicon,hip05-cpu-djtag-v1";
>>>> + reg = <0x0 0x80010000 0x0 0x10000>;
>>>> +
>>>> + /* For L3 cache PMU */
>>>> + pmul3c0 {
>>>> + compatible = "hisilicon,hisi-pmu-l3c-v1";
>>>> + scl-id = <0x02>;
>>>> + num-events = <0x16>;
>>>> + num-counters = <0x08>;
>>>> + module-id = <0x04>;
>>>> + num-banks = <0x04>;
>>>> + cfgen-map = <0x02 0x04 0x01 0x08>;
>>>> + counter-reg = <0x170>;
>>>> + evctrl-reg = <0x04>;
>>>> + event-en = <0x1000000>;
>>>> + evtype-reg = <0x140>;
>>>> + };
>>> This sub-node needs a binding document.
>>>
>>> These properties are completely opaque
>> The L3 cache PMU bindings are defined @bindings/arm/hisilicon/pmu.txt.
>> Is it OK that I document here(hisilicon/djtag.txt), a reference to
>> the PMU bindings doc ?
> At this point in the series, that file does not exist yet, and this is
> an undocumented beinding.
>
> Please introduce this sub-node long with the PMU bindings, later in the
> series.
Thanks, I got your suggestion. Will add this later in series.
> Thanks,
> Mark.
^ permalink raw reply
* [PATCH v9 10/10] drm/mediatek: add support for Mediatek SoC MT2701
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
This patch add support for the Mediatek MT2701 DISP subsystem.
There is only one OVL engine in MT2701.
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 6 ++++++
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 6 ++++++
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 17 +++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 6 ++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 29 +++++++++++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_dsi.c | 1 +
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 6 ++++++
7 files changed, 71 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 1139834..d174905 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -286,11 +286,17 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt2701_ovl_driver_data = {
+ .ovl = {0x0040, 1 << 12, 0}
+};
+
static const struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
.ovl = {0x0f40, 0, 1 << 12}
};
static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
+ { .compatible = "mediatek,mt2701-disp-ovl",
+ .data = &mt2701_ovl_driver_data},
{ .compatible = "mediatek,mt8173-disp-ovl",
.data = &mt8173_ovl_driver_data},
{},
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index b4225e2..5d363de 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -226,11 +226,17 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt2701_rdma_driver_data = {
+ .rdma_fifo_pseudo_size = SZ_4K,
+};
+
static const struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
.rdma_fifo_pseudo_size = SZ_8K,
};
static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
+ { .compatible = "mediatek,mt2701-disp-rdma",
+ .data = &mt2701_rdma_driver_data},
{ .compatible = "mediatek,mt8173-disp-rdma",
.data = &mt8173_rdma_driver_data},
{},
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index a9b209c..8130f3d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -60,6 +60,13 @@
#define MT8173_MUTEX_MOD_DISP_PWM1 BIT(24)
#define MT8173_MUTEX_MOD_DISP_OD BIT(25)
+#define MT2701_MUTEX_MOD_DISP_OVL BIT(3)
+#define MT2701_MUTEX_MOD_DISP_WDMA BIT(6)
+#define MT2701_MUTEX_MOD_DISP_COLOR BIT(7)
+#define MT2701_MUTEX_MOD_DISP_BLS BIT(9)
+#define MT2701_MUTEX_MOD_DISP_RDMA0 BIT(10)
+#define MT2701_MUTEX_MOD_DISP_RDMA1 BIT(12)
+
#define MUTEX_SOF_SINGLE_MODE 0
#define MUTEX_SOF_DSI0 1
#define MUTEX_SOF_DSI1 2
@@ -92,6 +99,15 @@ struct mtk_ddp {
const unsigned int *mutex_mod;
};
+static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+ [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
+ [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
+ [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
+ [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0,
+ [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1,
+ [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
+};
+
static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
@@ -390,6 +406,7 @@ static int mtk_ddp_remove(struct platform_device *pdev)
}
static const struct of_device_id ddp_driver_dt_match[] = {
+ { .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod},
{ .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
{},
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index b78b2e6..60d4783 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -265,11 +265,17 @@ struct mtk_ddp_comp_match {
[DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL },
};
+static const struct mtk_ddp_comp_driver_data mt2701_color_driver_data = {
+ .color_offset = 0x0f00,
+};
+
static const struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
.color_offset = 0x0c00,
};
static const struct of_device_id mtk_disp_color_driver_dt_match[] = {
+ { .compatible = "mediatek,mt2701-disp-color",
+ .data = &mt2701_color_driver_data},
{ .compatible = "mediatek,mt8173-disp-color",
.data = &mt8173_color_driver_data},
{},
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 5f9b5e8..f5cb6f0 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -126,6 +126,19 @@ static int mtk_atomic_commit(struct drm_device *drm,
.atomic_commit = mtk_atomic_commit,
};
+static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
+ DDP_COMPONENT_OVL0,
+ DDP_COMPONENT_RDMA0,
+ DDP_COMPONENT_COLOR0,
+ DDP_COMPONENT_BLS,
+ DDP_COMPONENT_DSI0,
+};
+
+static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
+ DDP_COMPONENT_RDMA1,
+ DDP_COMPONENT_DPI0,
+};
+
static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0,
@@ -145,6 +158,14 @@ static int mtk_atomic_commit(struct drm_device *drm,
DDP_COMPONENT_DPI0,
};
+static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
+ .main_path = mt2701_mtk_ddp_main,
+ .main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
+ .ext_path = mt2701_mtk_ddp_ext,
+ .ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
+ .shadow_register = true,
+};
+
static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
.main_path = mt8173_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
@@ -340,16 +361,22 @@ static void mtk_drm_unbind(struct device *dev)
};
static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
+ { .compatible = "mediatek,mt2701-disp-ovl", .data = (void *)MTK_DISP_OVL },
{ .compatible = "mediatek,mt8173-disp-ovl", .data = (void *)MTK_DISP_OVL },
+ { .compatible = "mediatek,mt2701-disp-rdma", .data = (void *)MTK_DISP_RDMA },
{ .compatible = "mediatek,mt8173-disp-rdma", .data = (void *)MTK_DISP_RDMA },
{ .compatible = "mediatek,mt8173-disp-wdma", .data = (void *)MTK_DISP_WDMA },
+ { .compatible = "mediatek,mt2701-disp-color", .data = (void *)MTK_DISP_COLOR },
{ .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR },
{ .compatible = "mediatek,mt8173-disp-aal", .data = (void *)MTK_DISP_AAL},
{ .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, },
{ .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE },
+ { .compatible = "mediatek,mt2701-dsi", .data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8173-dsi", .data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8173-dpi", .data = (void *)MTK_DPI },
+ { .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
+ { .compatible = "mediatek,mt2701-disp-pwm", .data = (void *)MTK_DISP_BLS },
{ .compatible = "mediatek,mt8173-disp-pwm", .data = (void *)MTK_DISP_PWM },
{ .compatible = "mediatek,mt8173-disp-od", .data = (void *)MTK_DISP_OD },
{ }
@@ -522,6 +549,8 @@ static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
mtk_drm_sys_resume);
static const struct of_device_id mtk_drm_of_ids[] = {
+ { .compatible = "mediatek,mt2701-mmsys",
+ .data = &mt2701_mmsys_driver_data},
{ .compatible = "mediatek,mt8173-mmsys",
.data = &mt8173_mmsys_driver_data},
{ }
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 12a1206..fe9786c 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -1204,6 +1204,7 @@ static int mtk_dsi_remove(struct platform_device *pdev)
}
static const struct of_device_id mtk_dsi_of_match[] = {
+ { .compatible = "mediatek,mt2701-dsi" },
{ .compatible = "mediatek,mt8173-dsi" },
{ },
};
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
index 34e95c6..944fb1d 100644
--- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
+++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
@@ -467,11 +467,17 @@ static int mtk_mipi_tx_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_mipitx_data mt2701_mipitx_data = {
+ .data = (3 << 8)
+};
+
static const struct mtk_mipitx_data mt8173_mipitx_data = {
.data = (0 << 8)
};
static const struct of_device_id mtk_mipi_tx_match[] = {
+ { .compatible = "mediatek,mt2701-mipi-tx",
+ .data = &mt2701_mipitx_data },
{ .compatible = "mediatek,mt8173-mipi-tx",
.data = &mt8173_mipitx_data },
{},
--
1.9.1
^ permalink raw reply related
* [PATCH v9 09/10] drm/mediatek: update DSI sub driver flow for sending commands to panel
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
This patch update enable/disable flow of DSI module and MIPI TX module.
Original flow works on there is a bridge chip: DSI -> bridge -> panel.
In this case: DSI -> panel, the DSI sub driver flow should be updated.
We need to initialize DSI first so that we can send commands to panel.
Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 110 ++++++++++++++++++++++++++-------
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 32 +++++-----
2 files changed, 103 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 860b84f..12a1206 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -94,6 +94,8 @@
#define DSI_RACK 0x84
#define RACK BIT(0)
+#define DSI_MEM_CONTI 0x90
+
#define DSI_PHY_LCCON 0x104
#define LC_HS_TX_EN BIT(0)
#define LC_ULPM_EN BIT(1)
@@ -126,6 +128,10 @@
#define CLK_HS_POST (0xff << 8)
#define CLK_HS_EXIT (0xff << 16)
+#define DSI_VM_CMD_CON 0x130
+#define VM_CMD_EN BIT(0)
+#define TS_VFP_EN BIT(5)
+
#define DSI_CMDQ0 0x180
#define CONFIG (0xff << 0)
#define SHORT_PACKET 0
@@ -219,12 +225,12 @@ static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
writel(timcon3, dsi->regs + DSI_PHY_TIMECON3);
}
-static void mtk_dsi_enable(struct mtk_dsi *dsi)
+static void mtk_dsi_engine_enable(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, DSI_EN);
}
-static void mtk_dsi_disable(struct mtk_dsi *dsi)
+static void mtk_dsi_engine_disable(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0);
}
@@ -249,7 +255,9 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
* mipi_ratio is mipi clk coefficient for balance the pixel clk in mipi.
* we set mipi_ratio is 1.05.
*/
- dsi->data_rate = dsi->vm.pixelclock * 3 * 21 / (1 * 1000 * 10);
+ dsi->data_rate = dsi->vm.pixelclock * 12 * 21;
+ dsi->data_rate /= (dsi->lanes * 1000 * 10);
+ dev_info(dev, "set mipitx's data rate: %dMHz\n", dsi->data_rate);
ret = clk_set_rate(dsi->hs_clk, dsi->data_rate * 1000000);
if (ret < 0) {
@@ -271,7 +279,7 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
goto err_disable_engine_clk;
}
- mtk_dsi_enable(dsi);
+ mtk_dsi_engine_enable(dsi);
mtk_dsi_reset_engine(dsi);
mtk_dsi_phy_timconfig(dsi);
@@ -289,7 +297,7 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
- mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
+ mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, LC_ULPM_EN);
}
static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
@@ -302,7 +310,7 @@ static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0);
- mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
+ mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, LD0_ULPM_EN);
}
static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
@@ -338,11 +346,21 @@ static void mtk_dsi_set_mode(struct mtk_dsi *dsi)
if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) &&
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
vid_mode = BURST_MODE;
+ else
+ vid_mode = SYNC_EVENT_MODE;
}
writel(vid_mode, dsi->regs + DSI_MODE_CTRL);
}
+static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi)
+{
+ writel(0x3c, dsi->regs + DSI_MEM_CONTI);
+
+ mtk_dsi_mask(dsi, DSI_VM_CMD_CON, VM_CMD_EN, VM_CMD_EN);
+ mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN);
+}
+
static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi)
{
struct videomode *vm = &dsi->vm;
@@ -399,6 +417,9 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
break;
}
+ tmp_reg |= (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6;
+ tmp_reg |= (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3;
+
writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
}
@@ -477,6 +498,16 @@ static void mtk_dsi_start(struct mtk_dsi *dsi)
writel(1, dsi->regs + DSI_START);
}
+static void mtk_dsi_stop(struct mtk_dsi *dsi)
+{
+ writel(0, dsi->regs + DSI_START);
+}
+
+static void mtk_dsi_set_cmd_mode(struct mtk_dsi *dsi)
+{
+ writel(CMD_MODE, dsi->regs + DSI_MODE_CTRL);
+}
+
static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi)
{
u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
@@ -506,7 +537,7 @@ static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
if (ret == 0) {
dev_info(dsi->dev, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
- mtk_dsi_enable(dsi);
+ mtk_dsi_engine_enable(dsi);
mtk_dsi_reset_engine(dsi);
}
@@ -535,6 +566,17 @@ static irqreturn_t mtk_dsi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t)
+{
+ mtk_dsi_irq_data_clear(dsi, irq_flag);
+ mtk_dsi_set_cmd_mode(dsi);
+
+ if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag, t))
+ return -1;
+ else
+ return 0;
+}
+
static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
{
if (WARN_ON(dsi->refcount == 0))
@@ -543,11 +585,6 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
if (--dsi->refcount != 0)
return;
- mtk_dsi_lane0_ulp_mode_enter(dsi);
- mtk_dsi_clk_ulp_mode_enter(dsi);
-
- mtk_dsi_disable(dsi);
-
clk_disable_unprepare(dsi->engine_clk);
clk_disable_unprepare(dsi->digital_clk);
@@ -561,35 +598,45 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
if (dsi->enabled)
return;
- if (dsi->panel) {
- if (drm_panel_prepare(dsi->panel)) {
- DRM_ERROR("failed to setup the panel\n");
- return;
- }
- }
-
ret = mtk_dsi_poweron(dsi);
if (ret < 0) {
DRM_ERROR("failed to power on dsi\n");
return;
}
+ usleep_range(20000, 21000);
+
mtk_dsi_rxtx_control(dsi);
+ mtk_dsi_phy_timconfig(dsi);
+ mtk_dsi_ps_control_vact(dsi);
+ mtk_dsi_set_vm_cmd(dsi);
+ mtk_dsi_config_vdo_timing(dsi);
+ mtk_dsi_set_interrupt_enable(dsi);
+ mtk_dsi_engine_enable(dsi);
mtk_dsi_clk_ulp_mode_leave(dsi);
mtk_dsi_lane0_ulp_mode_leave(dsi);
mtk_dsi_clk_hs_mode(dsi, 0);
- mtk_dsi_set_mode(dsi);
- mtk_dsi_ps_control_vact(dsi);
- mtk_dsi_config_vdo_timing(dsi);
- mtk_dsi_set_interrupt_enable(dsi);
+ if (dsi->panel) {
+ if (drm_panel_prepare(dsi->panel)) {
+ DRM_ERROR("failed to prepare the panel\n");
+ return;
+ }
+ }
mtk_dsi_set_mode(dsi);
mtk_dsi_clk_hs_mode(dsi, 1);
mtk_dsi_start(dsi);
+ if (dsi->panel) {
+ if (drm_panel_enable(dsi->panel)) {
+ DRM_ERROR("failed to enable the panel\n");
+ return;
+ }
+ }
+
dsi->enabled = true;
}
@@ -605,6 +652,21 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi)
}
}
+ mtk_dsi_stop(dsi);
+ mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
+
+ if (dsi->panel) {
+ if (drm_panel_unprepare(dsi->panel)) {
+ DRM_ERROR("failed to unprepare the panel\n");
+ return;
+ }
+ }
+
+ mtk_dsi_reset_engine(dsi);
+ mtk_dsi_lane0_ulp_mode_enter(dsi);
+ mtk_dsi_clk_ulp_mode_enter(dsi);
+ mtk_dsi_engine_disable(dsi);
+
mtk_dsi_poweroff(dsi);
dsi->enabled = false;
@@ -845,7 +907,7 @@ static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
if (timeout_ms == 0) {
dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
- mtk_dsi_enable(dsi);
+ mtk_dsi_engine_enable(dsi);
mtk_dsi_reset_engine(dsi);
}
}
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
index 108d31a..34e95c6 100644
--- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
+++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
@@ -177,7 +177,9 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate);
- if (mipi_tx->data_rate >= 500000000) {
+ if (mipi_tx->data_rate > 1250000000) {
+ return -EINVAL;
+ } else if (mipi_tx->data_rate >= 500000000) {
txdiv = 1;
txdiv0 = 0;
txdiv1 = 0;
@@ -201,6 +203,10 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
return -EINVAL;
}
+ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON,
+ RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
+ (8 << 4) | RG_DSI_LNT_HS_BIAS_EN);
+
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_BG_CON,
RG_DSI_VOUT_MSK |
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN,
@@ -210,24 +216,18 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
usleep_range(30, 100);
- mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON,
- RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
- (8 << 4) | RG_DSI_LNT_HS_BIAS_EN);
-
- mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_CON,
- RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
+ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_CON,
+ RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN,
+ RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
RG_DSI_MPPLL_SDM_PWR_ON |
RG_DSI_MPPLL_SDM_ISO_EN,
RG_DSI_MPPLL_SDM_PWR_ON);
- mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
- RG_DSI_MPPLL_PLL_EN);
-
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
- RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 |
- RG_DSI_MPPLL_PREDIV,
+ RG_DSI_MPPLL_PREDIV | RG_DSI_MPPLL_TXDIV0 |
+ RG_DSI_MPPLL_TXDIV1 | RG_DSI_MPPLL_POSDIV,
(txdiv0 << 3) | (txdiv1 << 5));
/*
@@ -242,10 +242,12 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
26000000);
writel(pcw, mipi_tx->regs + MIPITX_DSI_PLL_CON2);
- mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
- RG_DSI_MPPLL_SDM_FRA_EN);
+ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
+ RG_DSI_MPPLL_SDM_FRA_EN,
+ RG_DSI_MPPLL_SDM_FRA_EN);
- mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
+ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
+ RG_DSI_MPPLL_PLL_EN, RG_DSI_MPPLL_PLL_EN);
usleep_range(20, 100);
--
1.9.1
^ permalink raw reply related
* [PATCH v9 08/10] drm/mediatek: add dsi transfer function
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
From: shaoming chen <shaoming.chen@mediatek.com>
add dsi read/write commands for transfer function
Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 168 ++++++++++++++++++++++++++++++++++++-
1 file changed, 166 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index e5832837..860b84f 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -24,6 +24,7 @@
#include <linux/of_graph.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <video/mipi_display.h>
#include <video/videomode.h>
#include "mtk_drm_ddp_comp.h"
@@ -80,8 +81,16 @@
#define DSI_HBP_WC 0x54
#define DSI_HFP_WC 0x58
+#define DSI_CMDQ_SIZE 0x60
+#define CMDQ_SIZE 0x3f
+
#define DSI_HSTX_CKL_WC 0x64
+#define DSI_RX_DATA0 0x74
+#define DSI_RX_DATA1 0x78
+#define DSI_RX_DATA2 0x7c
+#define DSI_RX_DATA3 0x80
+
#define DSI_RACK 0x84
#define RACK BIT(0)
@@ -117,8 +126,23 @@
#define CLK_HS_POST (0xff << 8)
#define CLK_HS_EXIT (0xff << 16)
+#define DSI_CMDQ0 0x180
+#define CONFIG (0xff << 0)
+#define SHORT_PACKET 0
+#define LONG_PACKET 2
+#define BTA BIT(2)
+#define DATA_ID (0xff << 8)
+#define DATA_0 (0xff << 16)
+#define DATA_1 (0xff << 24)
+
#define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
+#define MTK_DSI_HOST_IS_READ(type) \
+ ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
+ (type == MIPI_DSI_DCS_READ))
+
struct phy;
struct mtk_dsi {
@@ -465,12 +489,12 @@ static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit)
dsi->irq_data |= irq_bit;
}
-static __maybe_unused void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
+static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
{
dsi->irq_data &= ~irq_bit;
}
-static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
+static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
unsigned int timeout)
{
s32 ret = 0;
@@ -807,9 +831,149 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
return 0;
}
+static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
+{
+ u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
+
+ while (timeout_ms--) {
+ if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
+ break;
+
+ usleep_range(2, 4);
+ }
+
+ if (timeout_ms == 0) {
+ dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
+
+ mtk_dsi_enable(dsi);
+ mtk_dsi_reset_engine(dsi);
+ }
+}
+
+static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data)
+{
+ switch (type) {
+ case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+ return 1;
+ case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+ return 2;
+ case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
+ case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
+ return read_data[1] + read_data[2] * 16;
+ case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+ DRM_INFO("type is 0x02, try again\n");
+ break;
+ default:
+ DRM_INFO("type(0x%x) cannot be non-recognite\n", type);
+ break;
+ }
+
+ return 0;
+}
+
+static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
+{
+ const char *tx_buf = msg->tx_buf;
+ u8 config, cmdq_size, cmdq_off, type = msg->type;
+ u32 reg_val, cmdq_mask, i;
+
+ if (MTK_DSI_HOST_IS_READ(type))
+ config = BTA;
+ else
+ config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET;
+
+ if (msg->tx_len > 2) {
+ cmdq_size = 1 + (msg->tx_len + 3) / 4;
+ cmdq_off = 4;
+ cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
+ reg_val = (msg->tx_len << 16) | (type << 8) | config;
+ } else {
+ cmdq_size = 1;
+ cmdq_off = 2;
+ cmdq_mask = CONFIG | DATA_ID;
+ reg_val = (type << 8) | config;
+ }
+
+ for (i = 0; i < msg->tx_len; i++)
+ writeb(tx_buf[i], dsi->regs + DSI_CMDQ0 + cmdq_off + i);
+
+ mtk_dsi_mask(dsi, DSI_CMDQ0, cmdq_mask, reg_val);
+ mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size);
+}
+
+static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi,
+ const struct mipi_dsi_msg *msg, u8 flag)
+{
+ mtk_dsi_wait_for_idle(dsi);
+ mtk_dsi_irq_data_clear(dsi, flag);
+ mtk_dsi_cmdq(dsi, msg);
+ mtk_dsi_start(dsi);
+
+ if (!mtk_dsi_wait_for_irq_done(dsi, flag, 2000))
+ return -1;
+ else
+ return 0;
+}
+
+static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ const struct mipi_dsi_msg *msg)
+{
+ struct mtk_dsi *dsi = host_to_dsi(host);
+ u32 recv_cnt, i;
+ u8 read_data[16];
+ void *src_addr;
+ u8 irq_flag = CMD_DONE_INT_FLAG;
+
+ if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) {
+ dev_info(dsi->dev, "dsi engine is not command mode\n");
+ return -1;
+ }
+
+ if (MTK_DSI_HOST_IS_READ(msg->type))
+ irq_flag |= LPRX_RD_RDY_INT_FLAG;
+
+ if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0)
+ return -1;
+
+ if (!MTK_DSI_HOST_IS_READ(msg->type))
+ return 0;
+
+ if (!msg->rx_buf) {
+ dev_info(dsi->dev, "dsi receive buffer size may be NULL\n");
+ return -1;
+ }
+
+ for (i = 0; i < 16; i++)
+ *(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i);
+
+ recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data);
+
+ if (recv_cnt > 2)
+ src_addr = &read_data[4];
+ else
+ src_addr = &read_data[1];
+
+ if (recv_cnt > 10)
+ recv_cnt = 10;
+
+ if (recv_cnt > msg->rx_len)
+ recv_cnt = msg->rx_len;
+
+ if (recv_cnt)
+ memcpy(msg->rx_buf, src_addr, recv_cnt);
+
+ dev_info(dsi->dev, "dsi get %d byte data from the panel address(0x%x)\n",
+ recv_cnt, *((u8 *)(msg->tx_buf)));
+
+ return recv_cnt;
+}
+
static const struct mipi_dsi_host_ops mtk_dsi_ops = {
.attach = mtk_dsi_host_attach,
.detach = mtk_dsi_host_detach,
+ .transfer = mtk_dsi_host_transfer,
};
static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
--
1.9.1
^ permalink raw reply related
* [PATCH v9 07/10] drm/mediatek: add dsi interrupt control
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
From: shaoming chen <shaoming.chen@mediatek.com>
add dsi interrupt control
Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 93 ++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 4efeb38..e5832837 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -18,6 +18,7 @@
#include <drm/drm_panel.h>
#include <linux/clk.h>
#include <linux/component.h>
+#include <linux/irq.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_graph.h>
@@ -29,6 +30,16 @@
#define DSI_START 0x00
+#define DSI_INTEN 0x08
+
+#define DSI_INTSTA 0x0c
+#define LPRX_RD_RDY_INT_FLAG BIT(0)
+#define CMD_DONE_INT_FLAG BIT(1)
+#define TE_RDY_INT_FLAG BIT(2)
+#define VM_DONE_INT_FLAG BIT(3)
+#define EXT_TE_RDY_INT_FLAG BIT(4)
+#define DSI_BUSY BIT(31)
+
#define DSI_CON_CTRL 0x10
#define DSI_RESET BIT(0)
#define DSI_EN BIT(1)
@@ -71,6 +82,9 @@
#define DSI_HSTX_CKL_WC 0x64
+#define DSI_RACK 0x84
+#define RACK BIT(0)
+
#define DSI_PHY_LCCON 0x104
#define LC_HS_TX_EN BIT(0)
#define LC_ULPM_EN BIT(1)
@@ -131,6 +145,8 @@ struct mtk_dsi {
struct videomode vm;
int refcount;
bool enabled;
+ u32 irq_data;
+ wait_queue_head_t irq_wait_queue;
};
static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e)
@@ -437,6 +453,64 @@ static void mtk_dsi_start(struct mtk_dsi *dsi)
writel(1, dsi->regs + DSI_START);
}
+static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi)
+{
+ u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
+
+ writel(inten, dsi->regs + DSI_INTEN);
+}
+
+static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit)
+{
+ dsi->irq_data |= irq_bit;
+}
+
+static __maybe_unused void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
+{
+ dsi->irq_data &= ~irq_bit;
+}
+
+static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
+ unsigned int timeout)
+{
+ s32 ret = 0;
+ unsigned long jiffies = msecs_to_jiffies(timeout);
+
+ ret = wait_event_interruptible_timeout(dsi->irq_wait_queue,
+ dsi->irq_data & irq_flag,
+ jiffies);
+ if (ret == 0) {
+ dev_info(dsi->dev, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
+
+ mtk_dsi_enable(dsi);
+ mtk_dsi_reset_engine(dsi);
+ }
+
+ return ret;
+}
+
+static irqreturn_t mtk_dsi_irq(int irq, void *dev_id)
+{
+ struct mtk_dsi *dsi = dev_id;
+ u32 status, tmp;
+ u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
+
+ status = readl(dsi->regs + DSI_INTSTA) & flag;
+
+ if (status) {
+ do {
+ mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK);
+ tmp = readl(dsi->regs + DSI_INTSTA);
+ } while (tmp & DSI_BUSY);
+
+ mtk_dsi_mask(dsi, DSI_INTSTA, status, 0);
+ mtk_dsi_irq_data_set(dsi, status);
+ wake_up_interruptible(&dsi->irq_wait_queue);
+ }
+
+ return IRQ_HANDLED;
+}
+
static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
{
if (WARN_ON(dsi->refcount == 0))
@@ -485,6 +559,7 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
mtk_dsi_ps_control_vact(dsi);
mtk_dsi_config_vdo_timing(dsi);
+ mtk_dsi_set_interrupt_enable(dsi);
mtk_dsi_set_mode(dsi);
mtk_dsi_clk_hs_mode(dsi, 1);
@@ -793,6 +868,7 @@ static int mtk_dsi_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *remote_node, *endpoint;
struct resource *regs;
+ int irq_num;
int comp_id;
int ret;
@@ -869,6 +945,23 @@ static int mtk_dsi_probe(struct platform_device *pdev)
return ret;
}
+ irq_num = platform_get_irq(pdev, 0);
+ if (irq_num < 0) {
+ dev_err(&pdev->dev, "failed to request dsi irq resource\n");
+ return -EPROBE_DEFER;
+ }
+
+ irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW);
+ ret = devm_request_irq(&pdev->dev, irq_num, mtk_dsi_irq,
+ IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request mediatek dsi irq\n");
+ return -EPROBE_DEFER;
+ }
+ dev_info(dev, "dsi irq num is 0x%x\n", irq_num);
+
+ init_waitqueue_head(&dsi->irq_wait_queue);
+
platform_set_drvdata(pdev, dsi);
return component_add(&pdev->dev, &mtk_dsi_component_ops);
--
1.9.1
^ permalink raw reply related
* [PATCH v9 06/10] drm/mediatek: cleaning up and refine
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
cleaning up unused define and refine function name and variable
Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 77 ++++++++++++++++------------------
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 8 ++--
2 files changed, 41 insertions(+), 44 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 28b2044..4efeb38 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -27,9 +27,6 @@
#include "mtk_drm_ddp_comp.h"
-#define DSI_VIDEO_FIFO_DEPTH (1920 / 4)
-#define DSI_HOST_FIFO_DEPTH 64
-
#define DSI_START 0x00
#define DSI_CON_CTRL 0x10
@@ -46,7 +43,7 @@
#define MIX_MODE BIT(17)
#define DSI_TXRX_CTRL 0x18
-#define VC_NUM (2 << 0)
+#define VC_NUM BIT(1)
#define LANE_NUM (0xf << 2)
#define DIS_EOT BIT(6)
#define NULL_EN BIT(7)
@@ -158,11 +155,11 @@ static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data)
writel((temp & ~mask) | (data & mask), dsi->regs + offset);
}
-static void dsi_phy_timconfig(struct mtk_dsi *dsi)
+static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
{
u32 timcon0, timcon1, timcon2, timcon3;
- unsigned int ui, cycle_time;
- unsigned int lpx;
+ u32 ui, cycle_time;
+ u32 lpx;
ui = 1000 / dsi->data_rate + 0x01;
cycle_time = 8000 / dsi->data_rate + 0x01;
@@ -192,7 +189,7 @@ static void mtk_dsi_disable(struct mtk_dsi *dsi)
mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0);
}
-static void mtk_dsi_reset(struct mtk_dsi *dsi)
+static void mtk_dsi_reset_engine(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET);
mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0);
@@ -235,8 +232,8 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
}
mtk_dsi_enable(dsi);
- mtk_dsi_reset(dsi);
- dsi_phy_timconfig(dsi);
+ mtk_dsi_reset_engine(dsi);
+ mtk_dsi_phy_timconfig(dsi);
return 0;
@@ -249,33 +246,33 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
return ret;
}
-static void dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
+static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
}
-static void dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
+static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN);
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0);
}
-static void dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi)
+static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0);
mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
}
-static void dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
+static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN);
mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0);
}
-static bool dsi_clk_hs_state(struct mtk_dsi *dsi)
+static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi)
{
u32 tmp_reg1;
@@ -283,15 +280,15 @@ static bool dsi_clk_hs_state(struct mtk_dsi *dsi)
return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false;
}
-static void dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter)
+static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter)
{
- if (enter && !dsi_clk_hs_state(dsi))
+ if (enter && !mtk_dsi_clk_hs_state(dsi))
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN);
- else if (!enter && dsi_clk_hs_state(dsi))
+ else if (!enter && mtk_dsi_clk_hs_state(dsi))
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
}
-static void dsi_set_mode(struct mtk_dsi *dsi)
+static void mtk_dsi_set_mode(struct mtk_dsi *dsi)
{
u32 vid_mode = CMD_MODE;
@@ -306,7 +303,7 @@ static void dsi_set_mode(struct mtk_dsi *dsi)
writel(vid_mode, dsi->regs + DSI_MODE_CTRL);
}
-static void dsi_ps_control_vact(struct mtk_dsi *dsi)
+static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi)
{
struct videomode *vm = &dsi->vm;
u32 dsi_buf_bpp, ps_wc;
@@ -340,7 +337,7 @@ static void dsi_ps_control_vact(struct mtk_dsi *dsi)
writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC);
}
-static void dsi_rxtx_control(struct mtk_dsi *dsi)
+static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
{
u32 tmp_reg;
@@ -365,9 +362,9 @@ static void dsi_rxtx_control(struct mtk_dsi *dsi)
writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
}
-static void dsi_ps_control(struct mtk_dsi *dsi)
+static void mtk_dsi_ps_control(struct mtk_dsi *dsi)
{
- unsigned int dsi_tmp_buf_bpp;
+ u32 dsi_tmp_buf_bpp;
u32 tmp_reg;
switch (dsi->format) {
@@ -397,12 +394,12 @@ static void dsi_ps_control(struct mtk_dsi *dsi)
writel(tmp_reg, dsi->regs + DSI_PSCTRL);
}
-static void dsi_config_vdo_timing(struct mtk_dsi *dsi)
+static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
{
- unsigned int horizontal_sync_active_byte;
- unsigned int horizontal_backporch_byte;
- unsigned int horizontal_frontporch_byte;
- unsigned int dsi_tmp_buf_bpp;
+ u32 horizontal_sync_active_byte;
+ u32 horizontal_backporch_byte;
+ u32 horizontal_frontporch_byte;
+ u32 dsi_tmp_buf_bpp;
struct videomode *vm = &dsi->vm;
@@ -431,7 +428,7 @@ static void dsi_config_vdo_timing(struct mtk_dsi *dsi)
writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
- dsi_ps_control(dsi);
+ mtk_dsi_ps_control(dsi);
}
static void mtk_dsi_start(struct mtk_dsi *dsi)
@@ -448,8 +445,8 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
if (--dsi->refcount != 0)
return;
- dsi_lane0_ulp_mode_enter(dsi);
- dsi_clk_ulp_mode_enter(dsi);
+ mtk_dsi_lane0_ulp_mode_enter(dsi);
+ mtk_dsi_clk_ulp_mode_enter(dsi);
mtk_dsi_disable(dsi);
@@ -479,18 +476,18 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
return;
}
- dsi_rxtx_control(dsi);
+ mtk_dsi_rxtx_control(dsi);
- dsi_clk_ulp_mode_leave(dsi);
- dsi_lane0_ulp_mode_leave(dsi);
- dsi_clk_hs_mode(dsi, 0);
- dsi_set_mode(dsi);
+ mtk_dsi_clk_ulp_mode_leave(dsi);
+ mtk_dsi_lane0_ulp_mode_leave(dsi);
+ mtk_dsi_clk_hs_mode(dsi, 0);
+ mtk_dsi_set_mode(dsi);
- dsi_ps_control_vact(dsi);
- dsi_config_vdo_timing(dsi);
+ mtk_dsi_ps_control_vact(dsi);
+ mtk_dsi_config_vdo_timing(dsi);
- dsi_set_mode(dsi);
- dsi_clk_hs_mode(dsi, 1);
+ mtk_dsi_set_mode(dsi);
+ mtk_dsi_clk_hs_mode(dsi, 1);
mtk_dsi_start(dsi);
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
index 935a8ef..108d31a 100644
--- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
+++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
@@ -134,7 +134,7 @@ struct mtk_mipitx_data {
struct mtk_mipi_tx {
struct device *dev;
void __iomem *regs;
- unsigned int data_rate;
+ u32 data_rate;
const struct mtk_mipitx_data *driver_data;
struct clk_hw pll_hw;
struct clk *pll;
@@ -172,7 +172,7 @@ static void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
{
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
- unsigned int txdiv, txdiv0, txdiv1;
+ u8 txdiv, txdiv0, txdiv1;
u64 pcw;
dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate);
@@ -326,7 +326,7 @@ static unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
static int mtk_mipi_tx_power_on_signal(struct phy *phy)
{
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
- unsigned int reg;
+ u32 reg;
for (reg = MIPITX_DSI_CLOCK_LANE;
reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
@@ -357,7 +357,7 @@ static int mtk_mipi_tx_power_on(struct phy *phy)
static void mtk_mipi_tx_power_off_signal(struct phy *phy)
{
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
- unsigned int reg;
+ u32 reg;
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON,
RG_DSI_PAD_TIE_LOW_EN);
--
1.9.1
^ permalink raw reply related
* [PATCH v9 05/10] drm/mediatek: update display module connections
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
update connections for OVL, RDMA, BLS, DSI
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index b77d456..a9b209c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -32,6 +32,10 @@
#define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN 0x0c8
#define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100
+#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030
+#define DISP_REG_CONFIG_OUT_SEL 0x04c
+#define DISP_REG_CONFIG_DSI_SEL 0x050
+
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
#define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
@@ -71,6 +75,10 @@
#define DPI0_SEL_IN_RDMA1 0x1
#define COLOR1_SEL_IN_OVL1 0x1
+#define OVL_MOUT_EN_RDMA 0x1
+#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8
+#define DSI_SEL_IN_BLS 0x0
+
struct mtk_disp_mutex {
int id;
bool claimed;
@@ -111,6 +119,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
*addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
value = OVL0_MOUT_EN_COLOR0;
+ } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
+ *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
+ value = OVL_MOUT_EN_RDMA;
} else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) {
*addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
value = OD_MOUT_EN_RDMA0;
@@ -148,6 +159,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
} else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
*addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
value = COLOR1_SEL_IN_OVL1;
+ } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
+ *addr = DISP_REG_CONFIG_DSI_SEL;
+ value = DSI_SEL_IN_BLS;
} else {
value = 0;
}
@@ -155,6 +169,15 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
return value;
}
+static void mtk_ddp_sout_sel(void __iomem *config_regs,
+ enum mtk_ddp_comp_id cur,
+ enum mtk_ddp_comp_id next)
+{
+ if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0)
+ writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
+ config_regs + DISP_REG_CONFIG_OUT_SEL);
+}
+
void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
enum mtk_ddp_comp_id cur,
enum mtk_ddp_comp_id next)
@@ -167,6 +190,8 @@ void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
writel_relaxed(reg, config_regs + addr);
}
+ mtk_ddp_sout_sel(config_regs, cur, next);
+
value = mtk_ddp_sel_in(cur, next, &addr);
if (value) {
reg = readl_relaxed(config_regs + addr) | value;
--
1.9.1
^ permalink raw reply related
* [PATCH v9 04/10] drm/mediatek: add BLS component
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
Add BLS component for PWM + GAMMA function
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 5 ++++-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 2 ++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 661a4a0..b78b2e6 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -235,6 +235,7 @@ static void mtk_gamma_set(struct mtk_ddp_comp *comp,
[MTK_DISP_PWM] = "pwm",
[MTK_DISP_MUTEX] = "mutex",
[MTK_DISP_OD] = "od",
+ [MTK_DISP_BLS] = "bls",
};
struct mtk_ddp_comp_match {
@@ -245,6 +246,7 @@ struct mtk_ddp_comp_match {
static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL] = { MTK_DISP_AAL, 0, &ddp_aal },
+ [DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL },
[DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color },
[DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color },
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL },
@@ -303,7 +305,8 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
comp->id = comp_id;
comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs;
- if (comp_id == DDP_COMPONENT_DPI0 ||
+ if (comp_id == DDP_COMPONENT_BLS ||
+ comp_id == DDP_COMPONENT_DPI0 ||
comp_id == DDP_COMPONENT_DSI0 ||
comp_id == DDP_COMPONENT_PWM0) {
comp->regs = NULL;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 2f6872a..30faf46 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -36,11 +36,13 @@ enum mtk_ddp_comp_type {
MTK_DISP_PWM,
MTK_DISP_MUTEX,
MTK_DISP_OD,
+ MTK_DISP_BLS,
MTK_DDP_COMP_TYPE_MAX,
};
enum mtk_ddp_comp_id {
DDP_COMPONENT_AAL,
+ DDP_COMPONENT_BLS,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_COLOR1,
DDP_COMPONENT_DPI0,
--
1.9.1
^ permalink raw reply related
* [PATCH v9 03/10] drm/mediatek: add shadow register support
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
We need to acquire mutex before using the resources,
and need to release it after finished.
So we don't need to write registers in the blanking period.
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 76 ++++++++++++++++++++-------------
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 25 +++++++++++
drivers/gpu/drm/mediatek/mtk_drm_ddp.h | 2 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
4 files changed, 75 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 01a21dd..a4f2b3a 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -329,6 +329,42 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
pm_runtime_put(drm->dev);
}
+static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
+{
+ struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+ struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
+ struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
+ unsigned int i;
+
+ /*
+ * TODO: instead of updating the registers here, we should prepare
+ * working registers in atomic_commit and let the hardware command
+ * queue update module registers on vblank.
+ */
+ if (state->pending_config) {
+ mtk_ddp_comp_config(ovl, state->pending_width,
+ state->pending_height,
+ state->pending_vrefresh, 0);
+
+ state->pending_config = false;
+ }
+
+ if (mtk_crtc->pending_planes) {
+ for (i = 0; i < OVL_LAYER_NR; i++) {
+ struct drm_plane *plane = &mtk_crtc->planes[i];
+ struct mtk_plane_state *plane_state;
+
+ plane_state = to_mtk_plane_state(plane->state);
+
+ if (plane_state->pending.config) {
+ mtk_ddp_comp_layer_config(ovl, i, plane_state);
+ plane_state->pending.config = false;
+ }
+ }
+ mtk_crtc->pending_planes = false;
+ }
+}
+
static void mtk_drm_crtc_enable(struct drm_crtc *crtc)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -405,6 +441,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+ struct mtk_drm_private *priv = crtc->dev->dev_private;
unsigned int pending_planes = 0;
int i;
@@ -423,6 +460,13 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
}
if (pending_planes)
mtk_crtc->pending_planes = true;
+
+ if (priv->data->shadow_register) {
+ mtk_disp_mutex_acquire(mtk_crtc->mutex);
+ mtk_crtc_ddp_config(crtc);
+ mtk_disp_mutex_release(mtk_crtc->mutex);
+ }
+
if (crtc->state->color_mgmt_changed)
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
@@ -471,36 +515,10 @@ static int mtk_drm_crtc_init(struct drm_device *drm,
void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
- unsigned int i;
+ struct mtk_drm_private *priv = crtc->dev->dev_private;
- /*
- * TODO: instead of updating the registers here, we should prepare
- * working registers in atomic_commit and let the hardware command
- * queue update module registers on vblank.
- */
- if (state->pending_config) {
- mtk_ddp_comp_config(ovl, state->pending_width,
- state->pending_height,
- state->pending_vrefresh, 0);
-
- state->pending_config = false;
- }
-
- if (mtk_crtc->pending_planes) {
- for (i = 0; i < OVL_LAYER_NR; i++) {
- struct drm_plane *plane = &mtk_crtc->planes[i];
- struct mtk_plane_state *plane_state;
-
- plane_state = to_mtk_plane_state(plane->state);
-
- if (plane_state->pending.config) {
- mtk_ddp_comp_layer_config(ovl, i, plane_state);
- plane_state->pending.config = false;
- }
- }
- mtk_crtc->pending_planes = false;
- }
+ if (!priv->data->shadow_register)
+ mtk_crtc_ddp_config(crtc);
mtk_drm_finish_page_flip(mtk_crtc);
}
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 8030769..b77d456 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -12,6 +12,7 @@
*/
#include <linux/clk.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -32,10 +33,13 @@
#define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
+#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
#define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
#define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n))
#define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n))
+#define INT_MUTEX BIT(1)
+
#define MT8173_MUTEX_MOD_DISP_OVL0 BIT(11)
#define MT8173_MUTEX_MOD_DISP_OVL1 BIT(12)
#define MT8173_MUTEX_MOD_DISP_RDMA0 BIT(13)
@@ -300,6 +304,27 @@ void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
}
+void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex)
+{
+ struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+ mutex[mutex->id]);
+ u32 tmp;
+
+ writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
+ writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id));
+ if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id),
+ tmp, tmp & INT_MUTEX, 1, 10000))
+ pr_err("could not acquire mutex %d\n", mutex->id);
+}
+
+void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex)
+{
+ struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+ mutex[mutex->id]);
+
+ writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id));
+}
+
static int mtk_ddp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
index 92c1175..f9a7991 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
@@ -37,5 +37,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
enum mtk_ddp_comp_id id);
void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex);
void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex);
#endif /* MTK_DRM_DDP_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index fa0b106..94f8b66 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -33,6 +33,7 @@ struct mtk_mmsys_driver_data {
unsigned int main_len;
const enum mtk_ddp_comp_id *ext_path;
unsigned int ext_len;
+ bool shadow_register;
};
struct mtk_drm_private {
--
1.9.1
^ permalink raw reply related
* [PATCH v9 02/10] drm/mediatek: add *driver_data for different hardware settings
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
There are some hardware settings changed, between MT8173 & MT2701:
DISP_OVL address offset changed, color format definition changed.
DISP_RDMA fifo size changed.
DISP_COLOR offset changed.
MIPI_TX pll setting changed.
And add prefix for mtk_ddp_main & mtk_ddp_ext & mutex_mod.
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 27 ++++++++++++++++-----------
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 11 +++++++++--
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 11 +++++++----
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 27 +++++++++++++++++++++------
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 13 +++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 25 ++++++++++++++++++-------
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 8 ++++++++
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 24 +++++++++++++++++++++++-
8 files changed, 115 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 019b7ca..1139834 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -35,13 +35,10 @@
#define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n))
-#define DISP_REG_OVL_ADDR(n) (0x0f40 + 0x20 * (n))
#define OVL_RDMA_MEM_GMC 0x40402020
#define OVL_CON_BYTE_SWAP BIT(24)
-#define OVL_CON_CLRFMT_RGB565 (0 << 12)
-#define OVL_CON_CLRFMT_RGB888 (1 << 12)
#define OVL_CON_CLRFMT_RGBA8888 (2 << 12)
#define OVL_CON_CLRFMT_ARGB8888 (3 << 12)
#define OVL_CON_AEN BIT(8)
@@ -137,18 +134,18 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
}
-static unsigned int ovl_fmt_convert(unsigned int fmt)
+static unsigned int ovl_fmt_convert(struct mtk_ddp_comp *comp, unsigned int fmt)
{
switch (fmt) {
default:
case DRM_FORMAT_RGB565:
- return OVL_CON_CLRFMT_RGB565;
+ return comp->data->ovl.fmt_rgb565;
case DRM_FORMAT_BGR565:
- return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP;
+ return comp->data->ovl.fmt_rgb565 | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_RGB888:
- return OVL_CON_CLRFMT_RGB888;
+ return comp->data->ovl.fmt_rgb888;
case DRM_FORMAT_BGR888:
- return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP;
+ return comp->data->ovl.fmt_rgb888 | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_RGBA8888:
return OVL_CON_CLRFMT_ARGB8888;
@@ -178,7 +175,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
if (!pending->enable)
mtk_ovl_layer_off(comp, idx);
- con = ovl_fmt_convert(fmt);
+ con = ovl_fmt_convert(comp, fmt);
if (idx != 0)
con |= OVL_CON_AEN | OVL_CON_ALPHA;
@@ -186,7 +183,8 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
- writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx));
+ writel_relaxed(addr, comp->regs + comp->data->ovl.addr_offset
+ + idx * 0x20);
if (pending->enable)
mtk_ovl_layer_on(comp, idx);
@@ -270,6 +268,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}
+ priv->ddp_comp.data = of_device_get_match_data(dev);
+
platform_set_drvdata(pdev, priv);
ret = component_add(dev, &mtk_disp_ovl_component_ops);
@@ -286,8 +286,13 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
+ .ovl = {0x0f40, 0, 1 << 12}
+};
+
static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
- { .compatible = "mediatek,mt8173-disp-ovl", },
+ { .compatible = "mediatek,mt8173-disp-ovl",
+ .data = &mt8173_ovl_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 0df05f9..b4225e2 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -123,7 +123,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
*/
threshold = width * height * vrefresh * 4 * 7 / 1000000;
reg = RDMA_FIFO_UNDERFLOW_EN |
- RDMA_FIFO_PSEUDO_SIZE(SZ_8K) |
+ RDMA_FIFO_PSEUDO_SIZE(comp->data->rdma_fifo_pseudo_size) |
RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON);
}
@@ -208,6 +208,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
return ret;
}
+ priv->ddp_comp.data = of_device_get_match_data(dev);
+
platform_set_drvdata(pdev, priv);
ret = component_add(dev, &mtk_disp_rdma_component_ops);
@@ -224,8 +226,13 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
+ .rdma_fifo_pseudo_size = SZ_8K,
+};
+
static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
- { .compatible = "mediatek,mt8173-disp-rdma", },
+ { .compatible = "mediatek,mt8173-disp-rdma",
+ .data = &mt8173_rdma_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 2fc4321..8030769 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -77,9 +77,10 @@ struct mtk_ddp {
struct clk *clk;
void __iomem *regs;
struct mtk_disp_mutex mutex[10];
+ const unsigned int *mutex_mod;
};
-static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
[DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
@@ -247,7 +248,7 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
break;
default:
reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
- reg |= mutex_mod[id];
+ reg |= ddp->mutex_mod[id];
writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
return;
}
@@ -273,7 +274,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
break;
default:
reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
- reg &= ~mutex_mod[id];
+ reg &= ~(ddp->mutex_mod[id]);
writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
break;
}
@@ -326,6 +327,8 @@ static int mtk_ddp_probe(struct platform_device *pdev)
return PTR_ERR(ddp->regs);
}
+ ddp->mutex_mod = of_device_get_match_data(dev);
+
platform_set_drvdata(pdev, ddp);
return 0;
@@ -337,7 +340,7 @@ static int mtk_ddp_remove(struct platform_device *pdev)
}
static const struct of_device_id ddp_driver_dt_match[] = {
- { .compatible = "mediatek,mt8173-disp-mutex" },
+ { .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
{},
};
MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index df33b3c..661a4a0 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -39,9 +39,8 @@
#define DISP_REG_UFO_START 0x0000
#define DISP_COLOR_CFG_MAIN 0x0400
-#define DISP_COLOR_START 0x0c00
-#define DISP_COLOR_WIDTH 0x0c50
-#define DISP_COLOR_HEIGHT 0x0c54
+#define DISP_COLOR_WIDTH 0x50
+#define DISP_COLOR_HEIGHT 0x54
#define DISP_AAL_EN 0x0000
#define DISP_AAL_SIZE 0x0030
@@ -107,15 +106,15 @@ static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
unsigned int h, unsigned int vrefresh,
unsigned int bpc)
{
- writel(w, comp->regs + DISP_COLOR_WIDTH);
- writel(h, comp->regs + DISP_COLOR_HEIGHT);
+ writel(w, comp->regs + comp->data->color_offset + DISP_COLOR_WIDTH);
+ writel(h, comp->regs + comp->data->color_offset + DISP_COLOR_HEIGHT);
}
static void mtk_color_start(struct mtk_ddp_comp *comp)
{
writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL,
comp->regs + DISP_COLOR_CFG_MAIN);
- writel(0x1, comp->regs + DISP_COLOR_START);
+ writel(0x1, comp->regs + comp->data->color_offset);
}
static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
@@ -264,6 +263,16 @@ struct mtk_ddp_comp_match {
[DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL },
};
+static const struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
+ .color_offset = 0x0c00,
+};
+
+static const struct of_device_id mtk_disp_color_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8173-disp-color",
+ .data = &mt8173_color_driver_data},
+ {},
+};
+
int mtk_ddp_comp_get_id(struct device_node *node,
enum mtk_ddp_comp_type comp_type)
{
@@ -286,6 +295,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
enum mtk_ddp_comp_type type;
struct device_node *larb_node;
struct platform_device *larb_pdev;
+ const struct of_device_id *match;
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
return -EINVAL;
@@ -310,6 +320,11 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
type = mtk_ddp_matches[comp_id].type;
+ if (type == MTK_DISP_COLOR) {
+ match = of_match_node(mtk_disp_color_driver_dt_match, node);
+ comp->data = match->data;
+ }
+
/* Only DMA capable components need the LARB property */
comp->larb_dev = NULL;
if (type != MTK_DISP_OVL &&
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 22a33ee..2f6872a 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -78,6 +78,18 @@ struct mtk_ddp_comp_funcs {
struct drm_crtc_state *state);
};
+struct mtk_ddp_comp_driver_data {
+ union {
+ struct ovl {
+ unsigned int addr_offset;
+ unsigned int fmt_rgb565;
+ unsigned int fmt_rgb888;
+ } ovl;
+ unsigned int rdma_fifo_pseudo_size;
+ unsigned int color_offset;
+ };
+};
+
struct mtk_ddp_comp {
struct clk *clk;
void __iomem *regs;
@@ -85,6 +97,7 @@ struct mtk_ddp_comp {
struct device *larb_dev;
enum mtk_ddp_comp_id id;
const struct mtk_ddp_comp_funcs *funcs;
+ const struct mtk_ddp_comp_driver_data *data;
};
static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index cf83f65..5f9b5e8 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -126,7 +126,7 @@ static int mtk_atomic_commit(struct drm_device *drm,
.atomic_commit = mtk_atomic_commit,
};
-static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
+static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_AAL,
@@ -137,7 +137,7 @@ static int mtk_atomic_commit(struct drm_device *drm,
DDP_COMPONENT_PWM0,
};
-static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
+static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
DDP_COMPONENT_OVL1,
DDP_COMPONENT_COLOR1,
DDP_COMPONENT_GAMMA,
@@ -145,6 +145,13 @@ static int mtk_atomic_commit(struct drm_device *drm,
DDP_COMPONENT_DPI0,
};
+static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
+ .main_path = mt8173_mtk_ddp_main,
+ .main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
+ .ext_path = mt8173_mtk_ddp_ext,
+ .ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext),
+};
+
static int mtk_drm_kms_init(struct drm_device *drm)
{
struct mtk_drm_private *private = drm->dev_private;
@@ -187,17 +194,19 @@ static int mtk_drm_kms_init(struct drm_device *drm)
* and each statically assigned to a crtc:
* OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
*/
- ret = mtk_drm_crtc_create(drm, mtk_ddp_main, ARRAY_SIZE(mtk_ddp_main));
+ ret = mtk_drm_crtc_create(drm, private->data->main_path,
+ private->data->main_len);
if (ret < 0)
goto err_component_unbind;
/* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
- ret = mtk_drm_crtc_create(drm, mtk_ddp_ext, ARRAY_SIZE(mtk_ddp_ext));
+ ret = mtk_drm_crtc_create(drm, private->data->ext_path,
+ private->data->ext_len);
if (ret < 0)
goto err_component_unbind;
/* Use OVL device for all DMA memory allocations */
- np = private->comp_node[mtk_ddp_main[0]] ?:
- private->comp_node[mtk_ddp_ext[0]];
+ np = private->comp_node[private->data->main_path[0]] ?:
+ private->comp_node[private->data->ext_path[0]];
pdev = of_find_device_by_node(np);
if (!pdev) {
ret = -ENODEV;
@@ -362,6 +371,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
mutex_init(&private->commit.lock);
INIT_WORK(&private->commit.work, mtk_atomic_work);
+ private->data = of_device_get_match_data(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
private->config_regs = devm_ioremap_resource(dev, mem);
@@ -512,7 +522,8 @@ static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
mtk_drm_sys_resume);
static const struct of_device_id mtk_drm_of_ids[] = {
- { .compatible = "mediatek,mt8173-mmsys", },
+ { .compatible = "mediatek,mt8173-mmsys",
+ .data = &mt8173_mmsys_driver_data},
{ }
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index aa93894..fa0b106 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -28,6 +28,13 @@
struct drm_property;
struct regmap;
+struct mtk_mmsys_driver_data {
+ const enum mtk_ddp_comp_id *main_path;
+ unsigned int main_len;
+ const enum mtk_ddp_comp_id *ext_path;
+ unsigned int ext_len;
+};
+
struct mtk_drm_private {
struct drm_device *drm;
struct device *dma_dev;
@@ -40,6 +47,7 @@ struct mtk_drm_private {
void __iomem *config_regs;
struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
+ const struct mtk_mmsys_driver_data *data;
struct {
struct drm_atomic_state *state;
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
index 1c366f8..935a8ef 100644
--- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
+++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
@@ -87,6 +88,9 @@
#define MIPITX_DSI_PLL_CON2 0x58
+#define MIPITX_DSI_PLL_TOP 0x64
+#define RG_DSI_MPPLL_PRESERVE (0xff << 8)
+
#define MIPITX_DSI_PLL_PWR 0x68
#define RG_DSI_MPPLL_SDM_PWR_ON BIT(0)
#define RG_DSI_MPPLL_SDM_ISO_EN BIT(1)
@@ -123,10 +127,15 @@
#define SW_LNT2_HSTX_PRE_OE BIT(24)
#define SW_LNT2_HSTX_OE BIT(25)
+struct mtk_mipitx_data {
+ const u32 data;
+};
+
struct mtk_mipi_tx {
struct device *dev;
void __iomem *regs;
unsigned int data_rate;
+ const struct mtk_mipitx_data *driver_data;
struct clk_hw pll_hw;
struct clk *pll;
};
@@ -243,6 +252,10 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
RG_DSI_MPPLL_SDM_SSC_EN);
+ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
+ RG_DSI_MPPLL_PRESERVE,
+ mipi_tx->driver_data->data);
+
return 0;
}
@@ -255,6 +268,9 @@ static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw)
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
RG_DSI_MPPLL_PLL_EN);
+ mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
+ RG_DSI_MPPLL_PRESERVE, 0);
+
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
RG_DSI_MPPLL_SDM_ISO_EN |
RG_DSI_MPPLL_SDM_PWR_ON,
@@ -391,6 +407,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
if (!mipi_tx)
return -ENOMEM;
+ mipi_tx->driver_data = of_device_get_match_data(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mipi_tx->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(mipi_tx->regs)) {
@@ -448,8 +465,13 @@ static int mtk_mipi_tx_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_mipitx_data mt8173_mipitx_data = {
+ .data = (0 << 8)
+};
+
static const struct of_device_id mtk_mipi_tx_match[] = {
- { .compatible = "mediatek,mt8173-mipi-tx", },
+ { .compatible = "mediatek,mt8173-mipi-tx",
+ .data = &mt8173_mipitx_data },
{},
};
--
1.9.1
^ permalink raw reply related
* [PATCH v9 01/10] drm/mediatek: rename macros, add chip prefix
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478865346-19043-1-git-send-email-yt.shen@mediatek.com>
Add MT8173 prefix for hardware related macros.
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 60 +++++++++++++++++-----------------
1 file changed, 30 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 17ba935..2fc4321 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -36,21 +36,21 @@
#define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n))
#define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n))
-#define MUTEX_MOD_DISP_OVL0 BIT(11)
-#define MUTEX_MOD_DISP_OVL1 BIT(12)
-#define MUTEX_MOD_DISP_RDMA0 BIT(13)
-#define MUTEX_MOD_DISP_RDMA1 BIT(14)
-#define MUTEX_MOD_DISP_RDMA2 BIT(15)
-#define MUTEX_MOD_DISP_WDMA0 BIT(16)
-#define MUTEX_MOD_DISP_WDMA1 BIT(17)
-#define MUTEX_MOD_DISP_COLOR0 BIT(18)
-#define MUTEX_MOD_DISP_COLOR1 BIT(19)
-#define MUTEX_MOD_DISP_AAL BIT(20)
-#define MUTEX_MOD_DISP_GAMMA BIT(21)
-#define MUTEX_MOD_DISP_UFOE BIT(22)
-#define MUTEX_MOD_DISP_PWM0 BIT(23)
-#define MUTEX_MOD_DISP_PWM1 BIT(24)
-#define MUTEX_MOD_DISP_OD BIT(25)
+#define MT8173_MUTEX_MOD_DISP_OVL0 BIT(11)
+#define MT8173_MUTEX_MOD_DISP_OVL1 BIT(12)
+#define MT8173_MUTEX_MOD_DISP_RDMA0 BIT(13)
+#define MT8173_MUTEX_MOD_DISP_RDMA1 BIT(14)
+#define MT8173_MUTEX_MOD_DISP_RDMA2 BIT(15)
+#define MT8173_MUTEX_MOD_DISP_WDMA0 BIT(16)
+#define MT8173_MUTEX_MOD_DISP_WDMA1 BIT(17)
+#define MT8173_MUTEX_MOD_DISP_COLOR0 BIT(18)
+#define MT8173_MUTEX_MOD_DISP_COLOR1 BIT(19)
+#define MT8173_MUTEX_MOD_DISP_AAL BIT(20)
+#define MT8173_MUTEX_MOD_DISP_GAMMA BIT(21)
+#define MT8173_MUTEX_MOD_DISP_UFOE BIT(22)
+#define MT8173_MUTEX_MOD_DISP_PWM0 BIT(23)
+#define MT8173_MUTEX_MOD_DISP_PWM1 BIT(24)
+#define MT8173_MUTEX_MOD_DISP_OD BIT(25)
#define MUTEX_SOF_SINGLE_MODE 0
#define MUTEX_SOF_DSI0 1
@@ -80,21 +80,21 @@ struct mtk_ddp {
};
static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = {
- [DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL,
- [DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0,
- [DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1,
- [DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA,
- [DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD,
- [DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0,
- [DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1,
- [DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0,
- [DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1,
- [DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0,
- [DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1,
- [DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2,
- [DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE,
- [DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0,
- [DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1,
+ [DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL,
+ [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
+ [DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
+ [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA,
+ [DDP_COMPONENT_OD] = MT8173_MUTEX_MOD_DISP_OD,
+ [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0,
+ [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1,
+ [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0,
+ [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1,
+ [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0,
+ [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1,
+ [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2,
+ [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE,
+ [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0,
+ [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
};
static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
--
1.9.1
^ permalink raw reply related
* [PATCH v9 00/10] MT2701 DRM support
From: YT Shen @ 2016-11-11 11:55 UTC (permalink / raw)
To: linux-arm-kernel
This is MT2701 DRM support PATCH v9, based on 4.9-rc1.
We add DSI interrupt control, transfer function for MIPI DSI panel support.
Most codes are the same, except some register changed.
For example:
- DISP_OVL address offset changed, color format definition changed.
- DISP_RDMA fifo size changed.
- DISP_COLOR offset changed.
- MIPI_TX setting changed.
We add a new component DDP_COMPONENT_BLS, and the connections are updated.
OVL -> RDMA -> COLOR -> BLS -> DSI
RDMA -> DPI
And we have shadow register support in MT2701.
We remove dts patch from the patch series, which depends on MT2701 CCF and scpsys.
Changes since v8:
- enable 3 DSI interrupts only
- move mtk_dsi_wait_for_irq_done() to the patch of irq control
- use the name BLS in DRM driver part
- move BLS declaration to a separate patch
- update mtk_dsi_switch_to_cmd_mode()
- update mtk_output_dsi_enable() and mtk_output_dsi_disable()
Changes since v7:
- Remove redundant codes
- Move the definition of DDP_COMPONENT_BLS to patch of "drm/mediatek: update display module connections"
- Move _dsi_irq_wait_queue into platform driver data
- Move mtk_dsi_irq_data_clear() to patch of "drm/mediatek: add dsi interrupt control"
- Add more descriptions in the commit messages
Changes since v6:
- Change data type of irq_data to u32
- Rewrite mtk_dsi_host_transfer() for simplify
- Move some MIPI_TX config to patch of "drm/mediatek: add *driver_data for different hardware settings".
- Remove device tree from this patch series
Changes since v5:
- Remove DPI device tree and compatible string
- Use one wait queue to handle interrupt status
- Update the interrupt check flow and DSI_INT_ALL_BITS
- Use same function for host read/write command
- various fixes
Changes since v4:
- Add messages when timeout in mtk_disp_mutex_acquire()
- Add descriptions for DISP_REG_MUTEX registers
- Move connection settings for display modules to a separate patch
- Remove 'mt2701-disp-wdma' because it is unused
- Move cleaning up and renaming to a separate patch
- Use wait_event_interruptible_timeout() to replace polling
- Remove irq_num from mtk_dsi structure
- Remove redundant and debug codes
Changes since v3:
- Add DSI support for MIPI DSI panels
- Update BLS binding to PWM nodes
- Remove ufoe device nodes
- Remove redundant parentheses
- Remove global variable initialization
Changes since v2:
- Rename mtk_ddp_mux_sel to mtk_ddp_sout_sel
- Update mt2701_mtk_ddp_ext components
- Changed to prefix naming
- Reorder the patch series
- Use of_device_get_match_data() to get driver private data
- Use iopoll macros to implement mtk_disp_mutex_acquire()
- Removed empty device tree nodes
Changes since v1:
- Removed BLS bindings and codes, which belong to pwm driver
- Moved mtk_disp_mutex_acquire() just before mtk_crtc_ddp_config()
- Split patch into smaller parts
- Added const keyword to constant structure
- Removed codes for special memory align
Thanks,
yt.shen
YT Shen (8):
drm/mediatek: rename macros, add chip prefix
drm/mediatek: add *driver_data for different hardware settings
drm/mediatek: add shadow register support
drm/mediatek: add BLS component
drm/mediatek: update display module connections
drm/mediatek: cleaning up and refine
drm/mediatek: update DSI sub driver flow for sending commands to panel
drm/mediatek: add support for Mediatek SoC MT2701
shaoming chen (2):
drm/mediatek: add dsi interrupt control
drm/mediatek: add dsi transfer function
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 33 ++-
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 17 +-
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 76 +++--
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 138 ++++++---
drivers/gpu/drm/mediatek/mtk_drm_ddp.h | 2 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 38 ++-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 15 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 54 +++-
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 9 +
drivers/gpu/drm/mediatek/mtk_dsi.c | 429 ++++++++++++++++++++++++----
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 70 +++--
11 files changed, 715 insertions(+), 166 deletions(-)
--
1.9.1
^ permalink raw reply
* [RESEND PATCH v1 02/11] dt-bindings: hisi: Add Hisilicon HiP05/06/07 Sysctrl and Djtag dts bindings
From: Mark Rutland @ 2016-11-11 11:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5825A927.2000202@gmail.com>
On Fri, Nov 11, 2016 at 04:49:03PM +0530, Anurup M wrote:
> On Thursday 10 November 2016 10:53 PM, Mark Rutland wrote:
> >On Thu, Nov 03, 2016 at 01:41:58AM -0400, Anurup M wrote:
> >>diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> >>+Example:
> >>+ /* for Hisilicon HiP05 djtag for CPU sysctrl */
> >>+ djtag0: djtag at 80010000 {
> >>+ compatible = "hisilicon,hip05-cpu-djtag-v1";
> >>+ reg = <0x0 0x80010000 0x0 0x10000>;
> >>+
> >>+ /* For L3 cache PMU */
> >>+ pmul3c0 {
> >>+ compatible = "hisilicon,hisi-pmu-l3c-v1";
> >>+ scl-id = <0x02>;
> >>+ num-events = <0x16>;
> >>+ num-counters = <0x08>;
> >>+ module-id = <0x04>;
> >>+ num-banks = <0x04>;
> >>+ cfgen-map = <0x02 0x04 0x01 0x08>;
> >>+ counter-reg = <0x170>;
> >>+ evctrl-reg = <0x04>;
> >>+ event-en = <0x1000000>;
> >>+ evtype-reg = <0x140>;
> >>+ };
> >This sub-node needs a binding document.
> >
> >These properties are completely opaque
> The L3 cache PMU bindings are defined @bindings/arm/hisilicon/pmu.txt.
> Is it OK that I document here(hisilicon/djtag.txt), a reference to
> the PMU bindings doc ?
At this point in the series, that file does not exist yet, and this is
an undocumented beinding.
Please introduce this sub-node long with the PMU bindings, later in the
series.
Thanks,
Mark.
^ permalink raw reply
* [PATCH] PM / Domains: Fix compatible for domain idle state
From: Ulf Hansson @ 2016-11-11 11:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161110195832.4nz7lxlmshaemcbb@rob-hp-laptop>
On 10 November 2016 at 20:58, Rob Herring <robh@kernel.org> wrote:
>
> On Mon, Nov 07, 2016 at 12:14:28PM +0100, Ulf Hansson wrote:
> > On 3 November 2016 at 22:54, Lina Iyer <lina.iyer@linaro.org> wrote:
> > > Re-using idle state definition provided by arm,idle-state for domain
> > > idle states creates a lot of confusion and limits further evolution of
> > > the domain idle definition. To keep things clear and simple, define a
> > > idle states for domain using a new compatible "domain-idle-state".
> > >
> > > Fix existing PM domains code to look for the newly defined compatible.
> > >
> > > Cc: <devicetree@vger.kernel.org>
> > > Cc: Rob Herring <robh@kernel.org>
> > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > ---
> > > .../bindings/power/domain-idle-state.txt | 33 ++++++++++++++++++++++
> > > .../devicetree/bindings/power/power_domain.txt | 8 +++---
> > > drivers/base/power/domain.c | 2 +-
> > > 3 files changed, 38 insertions(+), 5 deletions(-)
> > > create mode 100644 Documentation/devicetree/bindings/power/domain-idle-state.txt
> > >
> > > diff --git a/Documentation/devicetree/bindings/power/domain-idle-state.txt b/Documentation/devicetree/bindings/power/domain-idle-state.txt
> > > new file mode 100644
> > > index 0000000..eefc7ed
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/power/domain-idle-state.txt
> > > @@ -0,0 +1,33 @@
> > > +PM Domain Idle State Node:
> > > +
> > > +A domain idle state node represents the state parameters that will be used to
> > > +select the state when there are no active components in the domain.
> > > +
> > > +The state node has the following parameters -
> > > +
> > > +- compatible:
> > > + Usage: Required
> > > + Value type: <string>
> > > + Definition: Must be "domain-idle-state".
> > > +
> > > +- entry-latency-us
> > > + Usage: Required
> > > + Value type: <prop-encoded-array>
> > > + Definition: u32 value representing worst case latency in
> > > + microseconds required to enter the idle state.
> > > + The exit-latency-us duration may be guaranteed
> > > + only after entry-latency-us has passed.
> >
> > As we anyway are going to change this, why not use an u64 and have the
> > value in ns instead of us?
>
> I can't imagine that you would need more resolution or range. For times
> less than 1us, s/w and register access times are going to dominate the
> time.
Yep.
>
>
> Unless there is a real need, I'd keep alignment with the existing
> binding.
Agree!
Kind regards
Uffe
^ permalink raw reply
* [PATCH v7] soc: qcom: add l2 cache perf events driver
From: Mark Rutland @ 2016-11-11 11:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50feb4f2-f042-5f75-732e-5a99653b51f2@codeaurora.org>
On Thu, Nov 10, 2016 at 06:25:47PM -0500, Leeder, Neil wrote:
> On 11/9/2016 12:54 PM, Mark Rutland wrote:
> >>+
> >>+/*
> >>+ * The cache is made up of one or more clusters, each cluster has its own PMU.
> >>+ * Each cluster is associated with one or more CPUs.
> >>+ * This structure represents one of the hardware PMUs.
> >>+ *
> >>+ * Events can be envisioned as a 2-dimensional array. Each column represents
> >>+ * a group of events. There are 8 groups. Only one entry from each
> >>+ * group can be in use at a time. When an event is assigned a counter
> >>+ * by *_event_add(), the counter index is assigned to group_to_counter[group].
> >
> >If I've followed correctly, this means each group has a dedicated
> >counter?
> >
> >I take it groups are not symmetric (i.e. each column has different
> >events)? Or does each column contain the same events?
> >
> >Is there any overlap?
>
> Each group will have at most one counter, but it's not dedicated.
> There's no requirement that an implementation have as many counters
> as there are groups, so an event can be assigned to any available
> counter.
>
> Every entry in the 2-dimensional array is unique, so no duplicates.
> Once you have used an event, you cannot use any other event from its
> column.
Ok; thanks for clarifying that!
> >>+static int l2_cache__event_init(struct perf_event *event)
> >>+ /* Don't allow groups with mixed PMUs, except for s/w events */
> >>+ if (event->group_leader->pmu != event->pmu &&
> >>+ !is_software_event(event->group_leader)) {
> >>+ dev_warn(&l2cache_pmu->pdev->dev,
> >>+ "Can't create mixed PMU group\n");
> >>+ return -EINVAL;
> >>+ }
> >>+
> >>+ list_for_each_entry(sibling, &event->group_leader->sibling_list,
> >>+ group_entry)
> >>+ if (sibling->pmu != event->pmu &&
> >>+ !is_software_event(sibling)) {
> >>+ dev_warn(&l2cache_pmu->pdev->dev,
> >>+ "Can't create mixed PMU group\n");
> >>+ return -EINVAL;
> >>+ }
> >>+
> >>+ /* Ensure all events in a group are on the same cpu */
> >>+ cluster = get_hml2_pmu(event->cpu);
> >>+ if ((event->group_leader != event) &&
> >>+ (cluster->on_cpu != event->group_leader->cpu)) {
> >>+ dev_warn(&l2cache_pmu->pdev->dev,
> >>+ "Can't create group on CPUs %d and %d",
> >>+ event->cpu, event->group_leader->cpu);
> >>+ return -EINVAL;
> >>+ }
> >
> >It's probably worth also checking that the events are co-schedulable
> >(e.g. they don't conflict column-wise).
>
> That's what filter_match() is doing - stopping column-conflicting
> events from even getting to init(). In init() we don't have a record
> of which other events are being co-scheduled. We could keep a list
> of groups used by other events to compare against, but because
> there's no matching term() function there's no obvious way of
> removing them from the list.
I mean within the group, in addition to the filter_match() logic.
When you event_init() an event, you can determine whether there is any
column conflict within the group the new events is being placed in, and
whether you have sufficient counters to ever be able to schedule that
group. If not, the group should be rejected.
Other PMUs have similar checks; see l2x0_pmu_group_is_valid() in
arch/arm/mm/cache-l2x0-pmu.c, and valiate_group() in
drivers/perf/arm_pmu.c.
I don't believe that filer_match() can catch that, as it's called on
each event in a group individually prior to add() time, and thus there's
no visibility of the group as a whole.
Regardless, we can and should catch that case far earlier.
[...]
> >>+ if (acpi_bus_get_device(ACPI_HANDLE(dev), &device))
> >>+ return -ENODEV;
> >>+
> >>+ if (kstrtol(device->pnp.unique_id, 10, &fw_cluster_id) < 0) {
> >>+ dev_err(&pdev->dev, "unable to read ACPI uid\n");
> >>+ return -ENODEV;
> >>+ }
> >
> >>+ cluster->l2cache_pmu = l2cache_pmu;
> >>+ for_each_present_cpu(cpu) {
> >>+ if (topology_physical_package_id(cpu) == fw_cluster_id) {
> >>+ cpumask_set_cpu(cpu, &cluster->cluster_cpus);
> >>+ per_cpu(pmu_cluster, cpu) = cluster;
> >>+ }
> >>+ }
> >
> >I'm still uneasy about this.
> >
> >The topology_* API doesn't have a well-defined mapping to the MPIDR.Aff*
> >levels, which itself also don't have a well-defined mapping to your
> >hardware's clusters (and therefore fw_cluster_id).
> >
> >Thus, I'm rather worried that this is going to get broken easily, either
> >by changes in the kernel, or in future HW revisions where the mapping of
> >clusters to MPIDR.Aff* fields changes.
>
> I'm not sure how else to get a mapping of CPU to cluster which
> doesn't eventually end with MPIDR.
This is unfortunate. :(
It would have been much nicer if the FW also provided the MPIDR.Aff<n>
level to match up to, as that would be unambiguous.
> This is the definition of topology_physical_package_id() from
> asm/topology.h:
>
> #define topology_physical_package_id(cpu)
> (cpu_topology[cpu].cluster_id)
>
> It seems to be a pretty solid connection between cpu and cluster.
As I mentioned above, there's no well-defined mapping from MPIDR.Aff* to
the topology API levels. The "cluster_id" here is a guess, and one that
might change in future based on other heuristics.
> I don't think this is an abuse of this function. Unless there is some
> other way of getting this mapping I'd suggest using this, and if some
> future chip should change MPIDR usage it can be addressed it then.
I don't think it's an abuse, as such, but I don't think that it is
reliable.
That said, I don't see that we can do any better, as you say.
It's probably worth adding a comment block regarding our expectations,
i.e. that cluster_id means Aff1 for CPUs without multi-threading, Aff2
otherwise, and that we hope future systems don't choose another
MPIDR.Aff* mapping scheme.
Thanks,
Mark.
^ permalink raw reply
* [RFC v2 8/8] iommu/arm-smmu: implement add_reserved_regions callback
From: Joerg Roedel @ 2016-11-11 11:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f4537e43-0237-e478-eacd-b107458628b8@redhat.com>
On Thu, Nov 10, 2016 at 07:00:52PM +0100, Auger Eric wrote:
> GICv2m and GICV3 ITS use dma-mapping iommu_dma_map_msi_msg to allocate
> an MSI IOVA on-demand.
Yes, and it the right thing to do there because as a DMA-API
implementation the dma-iommu code cares about the address space
allocation.
As I understand it this is different in your case, as someone else is
defining the address space layout. So why do you need to allocate it
yourself?
Joerg
^ permalink raw reply
* ACPI namespace details for ARM64
From: Lorenzo Pieralisi @ 2016-11-11 11:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109220506.GN14322@bhelgaas-glaptop.roam.corp.google.com>
On Wed, Nov 09, 2016 at 04:05:06PM -0600, Bjorn Helgaas wrote:
[...]
> ACPI defined a Producer/Consumer bit that was intended to distinguish
> the bridge apertures from the bridge registers [4, 5]. However, BIOSes
> didn't use that bit correctly, and the result is that OSes have to
> assume that everything in a PCI host bridge _CRS is a window. That
> leaves no way to describe the bridge registers in the PNP0A03/PNP0A08
> device itself.
ACPI 6.1 states that in the revision changes 4.0a Apr.2010 (xiii)
"Consumer/Producer bit is ignored (Restored 2.0C change that had
been lost)" and still that bit is marked as valid. If it is not
reliable it should be set as "ignored" in the specs (as it was
on ACPI 2.0C, BTW), as it is it is just a source of confusion.
Thanks again !
Lorenzo
^ permalink raw reply
* Summary of LPC guest MSI discussion in Santa Fe
From: Joerg Roedel @ 2016-11-11 11:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161110104601.0939ba9a@t450s.home>
On Thu, Nov 10, 2016 at 10:46:01AM -0700, Alex Williamson wrote:
> In the case of x86, we know that DMA mappings overlapping the MSI
> doorbells won't be translated correctly, it's not a valid mapping for
> that range, and therefore the iommu driver backing the IOMMU API
> should describe that reserved range and reject mappings to it.
The drivers actually allow mappings to the MSI region via the IOMMU-API,
and I think it should stay this way also for other reserved ranges.
Address space management is done by the IOMMU-API user already (and has
to be done there nowadays), be it a DMA-API implementation which just
reserves these regions in its address space allocator or be it VFIO with
QEMU, which don't map RAM there anyway. So there is no point of checking
this again in the IOMMU drivers and we can keep that out of the
mapping/unmapping fast-path.
> For PCI devices userspace can examine the topology of the iommu group
> and exclude MMIO ranges of peer devices based on the BARs, which are
> exposed in various places, pci-sysfs as well as /proc/iomem. For
> non-PCI or MSI controllers... ???
Right, the hardware resources can be examined. But maybe this can be
extended to also cover RMRR ranges? Then we would be able to assign
devices with RMRR mappings to guests.
Joerg
^ permalink raw reply
* [RESEND PATCH v1 02/11] dt-bindings: hisi: Add Hisilicon HiP05/06/07 Sysctrl and Djtag dts bindings
From: Anurup M @ 2016-11-11 11:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161110172320.GA10137@leverpostej>
On Thursday 10 November 2016 10:53 PM, Mark Rutland wrote:
> Hi,
>
> On Thu, Nov 03, 2016 at 01:41:58AM -0400, Anurup M wrote:
>> From: Tan Xiaojun <tanxiaojun@huawei.com>
>>
>> 1) Add Hisilicon HiP05/06/07 CPU and ALGSUB system controller dts
>> bindings.
>> 2) Add Hisilicon Djtag dts binding.
>>
>> Signed-off-by: Tan Xiaojun <tanxiaojun@huawei.com>
>> Signed-off-by: Anurup M <anurup.m@huawei.com>
>> ---
>> .../bindings/arm/hisilicon/hisilicon.txt | 82 ++++++++++++++++++++++
>> 1 file changed, 82 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> index 7df79a7..341cbb9 100644
>> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> @@ -270,3 +270,85 @@ Required Properties:
>> [1]: bootwrapper size
>> [2]: relocation physical address
>> [3]: relocation size
>
>> +-----------------------------------------------------------------------
>> +The Hisilicon Djtag in CPU die is an independent component which connects with
>> +some other components in the SoC by Debug Bus. This driver can be configured
>> +to access the registers of connecting components (like L3 cache, l3 cache PMU
>> + etc.) during real time debugging by sysctrl. These components appear as child
>> +nodes of djtag.
> Please put the djtag binding in a new file.
>
> It's clearly unrelated to many other things in this file, which should
> also be split out.
Ok. Shall move the djtag bindings to hisilicon/djtag.txt.
>> +The Hip05/06/07 CPU system controller(sysctrl) support to manage some important
>> +components (such as clock, reset, soft reset, secure debugger, etc.).
>> +The CPU sysctrl registers in hip05/06/07 doesnot use syscon but will be mapped
>> +by djtag driver for use by connecting components.
> The djtag driver is irrelvant here.
>
> If there's a realtionship between the two, please define that in the
> binding rather than implicitly assuming it in the driver.
Ok. I shall remove "djtag driver" and shall modify as
+The Hisilicon Djtag in CPU die is an independent component which connects with
+some other components in the SoC by Debug Bus. The djtag will use the system controller
+registers to access the connecting components in CPU die (like L3 cache, l3 cache PMU
+etc.) during real time debugging. These components appear as child nodes of djtag.
>> +
>> +Required properties:
>> + - compatible : "hisilicon,hip05-cpu-djtag-v1"
>> + - reg : Register address and size
>> +
>> +Hisilicon HiP06 djtag for CPU sysctrl
>> +Required properties:
>> +- compatible : "hisilicon,hip06-sysctrl", "syscon", "simple-mfd";
> This looks messy. Why is this syscon and a simple-mfd?
>
> We should kill off / deprecate the syscon binding. It's completely
> meaningless.
My Apologies. The syscon is not used now. Mistake in file version used
for patch creation.
The compatible filed will be "hisilicon,hisi-cpu-djtag-v1"
>> +- reg : Register address and size
>> +- djtag :
>> + - compatible : "hisilicon,hip06-cpu-djtag-v1"
>> + - reg : Register address and size
>> +
>> +Hisilicon HiP07 djtag for CPU sysctrl
>> +Required properties:
>> + - compatible : "hisilicon,hip07-cpu-djtag-v2"
>> + - reg : Register address and size
>> +
>> +Example:
>> + /* for Hisilicon HiP05 djtag for CPU sysctrl */
>> + djtag0: djtag at 80010000 {
>> + compatible = "hisilicon,hip05-cpu-djtag-v1";
>> + reg = <0x0 0x80010000 0x0 0x10000>;
>> +
>> + /* For L3 cache PMU */
>> + pmul3c0 {
>> + compatible = "hisilicon,hisi-pmu-l3c-v1";
>> + scl-id = <0x02>;
>> + num-events = <0x16>;
>> + num-counters = <0x08>;
>> + module-id = <0x04>;
>> + num-banks = <0x04>;
>> + cfgen-map = <0x02 0x04 0x01 0x08>;
>> + counter-reg = <0x170>;
>> + evctrl-reg = <0x04>;
>> + event-en = <0x1000000>;
>> + evtype-reg = <0x140>;
>> + };
> This sub-node needs a binding document.
>
> These properties are completely opaque
The L3 cache PMU bindings are defined @bindings/arm/hisilicon/pmu.txt.
Is it OK that I document here(hisilicon/djtag.txt), a reference to the
PMU bindings doc ?
>> + };
>> +
>> +-----------------------------------------------------------------------
>> +The Hisilicon HiP05/06/07 ALGSUB system controller(sysctrl) is in IO die
>> +of SoC. It has a similar function as the Hisilicon HiP05/06/07 CPU system
>> +controller in CPU die and it manage different components, like RSA, etc.
>> +The Hisilicon Djtag in IO die has a similar function as in CPU die and maps
>> +the sysctrl registers for use by connecting components.
>> +All connecting components shall appear as child nodes of djtag.
> I don't follow the above. This describes an ALGSUB system controllerm
> but the documentation below is all about djtag.
The ALGSUB is the name of the sysctrl of IO die. I shall remove ALGSUB
to avoid confusion.
I would also add the below details in the introduction.
The Hisilicon djtag will use the system controller registers to control
access to connecting modules
of CPU and IO die in the chip. There are separate system controller
registers for CPU and IO die in the chip.
And the section will be modified as
+Hisilicon HiP05 djtag for IO sysctrl
+Required properties:
+ - compatible : "hisilicon,hisi-io-djtag-v1"
+ - reg : Register address and size
+
+Hisilicon HiP06/07 djtag for IO sysctrl
+Required properties:
+ - compatible : "hisilicon,hip06-io-djtag-v2"
+ - reg : Register address and size
+
+Example:
+ /* for Hisilicon HiP05 djtag for IO sysctrl */
+ djtag0: djtag at d0000000 {
+ compatible = "hisilicon,hisi-io-djtag-v1";
+ reg = <0x0 0xd0000000 0x0 0x10000>;
+ };
Thanks,
Anurup
> Thanks,
> Mark.
>
>> +Hisilicon HiP05 djtag for ALGSUB sysctrl
>> +Required properties:
>> + - compatible : "hisilicon,hip05-io-djtag-v1"
>> + - reg : Register address and size
>> +
>> +Hisilicon HiP06 djtag for ALGSUB sysctrl
>> +Required properties:
>> + - compatible : "hisilicon,hip06-io-djtag-v2"
>> + - reg : Register address and size
>> +
>> +Hisilicon HiP07 djtag for ALGSUB sysctrl
>> +Required properties:
>> + - compatible : "hisilicon,hip07-io-djtag-v2"
>> + - reg : Register address and size
>> +
>> +Example:
>> + /* for Hisilicon HiP05 djtag for alg sysctrl */
>> + djtag0: djtag at d0000000 {
>> + compatible = "hisilicon,hip05-io-djtag-v1";
>> + reg = <0x0 0xd0000000 0x0 0x10000>;
>> + };
>> --
>> 2.1.4
>>
^ permalink raw reply
* [PATCH v4 1/5] arm64: perf: Basic uncore counter support for Cavium ThunderX SOC
From: Mark Rutland @ 2016-11-11 11:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161111103921.GE16907@hardcore>
On Fri, Nov 11, 2016 at 11:39:21AM +0100, Jan Glauber wrote:
> Hi Mark,
>
> thanks for reviewing. One question below,
> On Thu, Nov 10, 2016 at 04:54:06PM +0000, Mark Rutland wrote:
> > On Sat, Oct 29, 2016 at 01:55:29PM +0200, Jan Glauber wrote:
> > > +#include <linux/cpufeature.h>
> > > +#include <linux/numa.h>
> > > +#include <linux/slab.h>
> >
> > I believe the following includes are necessary for APIs and/or data
> > explicitly referenced by the driver code:
[...]
> Should I also add includes that are already in the included by uncore_cavium.h?
Please do.
> I usually avoid includes that come through the "local" header file.
Generally, when you explcitly use some macro/function/data in a file,
that file should have the relevant include.
If something's only used in the header (e.g. hidden in a macro or inline
function), then we only need that include in the header.
For example: uncore_cavium.h uses container_of(), and should include
<linux/kernel.h>. Also, uncore_cavium.c also uses container_of()
directly for something unrelated, and should also include
<linux/kernel.h>.
Thanks,
Mark.
^ permalink raw reply
* [PATCH v6 2/9] drm/hisilicon/hibmc: Add video memory management
From: Rongrong Zou @ 2016-11-11 11:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOw6vbKK+kmjZv+su4tg43Pcos-B3MjZcAv461au86SeqCQP=A@mail.gmail.com>
? 2016/11/11 1:35, Sean Paul ??:
> On Fri, Oct 28, 2016 at 3:27 AM, Rongrong Zou <zourongrong@gmail.com> wrote:
>> Hibmc have 32m video memory which can be accessed through PCIe by host,
>> we use ttm to manage these memory.
>>
>> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
>> ---
>> drivers/gpu/drm/hisilicon/hibmc/Kconfig | 1 +
>> drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +-
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 12 +
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 46 +++
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 490 ++++++++++++++++++++++++
>> 5 files changed, 550 insertions(+), 1 deletion(-)
>> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> index a9af90d..bcb8c18 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> @@ -1,6 +1,7 @@
>> config DRM_HISI_HIBMC
>> tristate "DRM Support for Hisilicon Hibmc"
>> depends on DRM && PCI
>> + select DRM_TTM
>>
>> help
>> Choose this option if you have a Hisilicon Hibmc soc chipset.
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> index 97cf4a0..d5c40b8 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> @@ -1,5 +1,5 @@
>> ccflags-y := -Iinclude/drm
>> -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o hibmc_ttm.o
>>
>> obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o
>> #obj-y += hibmc-drm.o
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> index 4669d42..81f4301 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> @@ -31,6 +31,7 @@
>> #ifdef CONFIG_COMPAT
>> .compat_ioctl = drm_compat_ioctl,
>> #endif
>> + .mmap = hibmc_mmap,
>> .poll = drm_poll,
>> .read = drm_read,
>> .llseek = no_llseek,
>> @@ -46,6 +47,8 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
>> }
>>
>> static struct drm_driver hibmc_driver = {
>> + .driver_features = DRIVER_GEM,
>> +
>
> nit: extra space
>
>> .fops = &hibmc_fops,
>> .name = "hibmc",
>> .date = "20160828",
>> @@ -55,6 +58,10 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
>> .get_vblank_counter = drm_vblank_no_hw_counter,
>> .enable_vblank = hibmc_enable_vblank,
>> .disable_vblank = hibmc_disable_vblank,
>> + .gem_free_object_unlocked = hibmc_gem_free_object,
>> + .dumb_create = hibmc_dumb_create,
>> + .dumb_map_offset = hibmc_dumb_mmap_offset,
>> + .dumb_destroy = drm_gem_dumb_destroy,
>> };
>>
>> static int hibmc_pm_suspend(struct device *dev)
>> @@ -163,6 +170,7 @@ static int hibmc_unload(struct drm_device *dev)
>> {
>> struct hibmc_drm_device *hidev = dev->dev_private;
>>
>> + hibmc_mm_fini(hidev);
>> hibmc_hw_fini(hidev);
>> dev->dev_private = NULL;
>> return 0;
>> @@ -183,6 +191,10 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
>> if (ret)
>> goto err;
>>
>> + ret = hibmc_mm_init(hidev);
>> + if (ret)
>> + goto err;
>> +
>> return 0;
>>
>> err:
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> index 0037341..db8d80e 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> @@ -20,6 +20,8 @@
>> #define HIBMC_DRM_DRV_H
>>
>> #include <drm/drmP.h>
>> +#include <drm/ttm/ttm_bo_driver.h>
>> +#include <drm/drm_gem.h>
>
> nit: alphabetize
will fix it, thanks.
>
>>
>> struct hibmc_drm_device {
>> /* hw */
>> @@ -30,6 +32,50 @@ struct hibmc_drm_device {
>>
>> /* drm */
>> struct drm_device *dev;
>> +
>> + /* ttm */
>> + struct {
>> + struct drm_global_reference mem_global_ref;
>> + struct ttm_bo_global_ref bo_global_ref;
>> + struct ttm_bo_device bdev;
>> + bool initialized;
>> + } ttm;
>
> I don't think you gain anything other than keystrokes from the substruct
I'm sorry i didn't catch you, i looked at the all drivers used ttm such
as ast/bochs/cirrus/mgag200/qxl/virtio_gpu, they all embedded the ttm substruct
into the driver-private struct.
so do you mean
struct hibmc_drm_device {
/* hw */
void __iomem *mmio;
void __iomem *fb_map;
unsigned long fb_base;
unsigned long fb_size;
/* drm */
struct drm_device *dev;
struct drm_plane plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
struct drm_connector connector;
bool mode_config_initialized;
/* ttm */
struct drm_global_reference mem_global_ref;
struct ttm_bo_global_ref bo_global_ref;
struct ttm_bo_device bdev;
bool initialized;
...
};
?
>
>> +
>> + bool mm_inited;
>> };
>>
>> +struct hibmc_bo {
>> + struct ttm_buffer_object bo;
>> + struct ttm_placement placement;
>> + struct ttm_bo_kmap_obj kmap;
>> + struct drm_gem_object gem;
>> + struct ttm_place placements[3];
>> + int pin_count;
>> +};
>> +
>> +static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo)
>> +{
>> + return container_of(bo, struct hibmc_bo, bo);
>> +}
>> +
>> +static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
>> +{
>> + return container_of(gem, struct hibmc_bo, gem);
>> +}
>> +
>> +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
>
> Hide this in ttm.c
ok, will do that.
thanks for pointing it out.
>
>> +
>> +int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
>> + struct drm_gem_object **obj);
>> +
>> +int hibmc_mm_init(struct hibmc_drm_device *hibmc);
>> +void hibmc_mm_fini(struct hibmc_drm_device *hibmc);
>> +int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr);
>> +void hibmc_gem_free_object(struct drm_gem_object *obj);
>> +int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
>> + struct drm_mode_create_dumb *args);
>> +int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
>> + u32 handle, u64 *offset);
>> +int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
>> +
>> #endif
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>> new file mode 100644
>> index 0000000..0802ebd
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>> @@ -0,0 +1,490 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + * Rongrong Zou <zourongrong@huawei.com>
>> + * Rongrong Zou <zourongrong@gmail.com>
>> + * Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + */
>> +
>> +#include "hibmc_drm_drv.h"
>> +#include <ttm/ttm_page_alloc.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_atomic_helper.h>
>> +
>> +static inline struct hibmc_drm_device *
>> +hibmc_bdev(struct ttm_bo_device *bd)
>> +{
>> + return container_of(bd, struct hibmc_drm_device, ttm.bdev);
>> +}
>> +
>> +static int
>> +hibmc_ttm_mem_global_init(struct drm_global_reference *ref)
>> +{
>> + return ttm_mem_global_init(ref->object);
>> +}
>> +
>> +static void
>> +hibmc_ttm_mem_global_release(struct drm_global_reference *ref)
>> +{
>> + ttm_mem_global_release(ref->object);
>> +}
>> +
>> +static int hibmc_ttm_global_init(struct hibmc_drm_device *hibmc)
>> +{
>> + struct drm_global_reference *global_ref;
>> + int r;
>
> nit: try not to use one character variable names unless it's for the
> purpose of a loop (ie: i,j). You also use ret elsewhere in the driver,
> so it'd be nice to remain consistent
the whole file is delivered from bochs ttm, i didn't modify anything except
some checkpatch warnings and the 'hibmc_' prefix. Unfortunately, some
problems were delivered too.
>
>> +
>> + global_ref = &hibmc->ttm.mem_global_ref;
>
> I think using the global_ref local obfuscates what you're doing here.
> It saves you 6 characters while typing, but adds a layer of
> indirection for all future readers.
>
>> + global_ref->global_type = DRM_GLOBAL_TTM_MEM;
>> + global_ref->size = sizeof(struct ttm_mem_global);
>> + global_ref->init = &hibmc_ttm_mem_global_init;
>> + global_ref->release = &hibmc_ttm_mem_global_release;
>> + r = drm_global_item_ref(global_ref);
>> + if (r != 0) {
>
> nit: if (r)
will fix it,
thanks.
BTW, i wonder why checkpatch.pl didn't report it.
>
>> + DRM_ERROR("Failed setting up TTM memory accounting subsystem.\n"
>> + );
>
> Breaking up the line for one character is probably not worthwhile, and
> you should really print the error. How about:
>
> DRM_ERROR("Could not get ref on ttm global ret=%d.\n", ret);
i like your solution, thanks.
>
>
>> + return r;
>> + }
>> +
>> + hibmc->ttm.bo_global_ref.mem_glob =
>> + hibmc->ttm.mem_global_ref.object;
>> + global_ref = &hibmc->ttm.bo_global_ref.ref;
>> + global_ref->global_type = DRM_GLOBAL_TTM_BO;
>> + global_ref->size = sizeof(struct ttm_bo_global);
>> + global_ref->init = &ttm_bo_global_init;
>> + global_ref->release = &ttm_bo_global_release;
>> + r = drm_global_item_ref(global_ref);
>> + if (r != 0) {
>> + DRM_ERROR("Failed setting up TTM BO subsystem.\n");
>> + drm_global_item_unref(&hibmc->ttm.mem_global_ref);
>> + return r;
>> + }
>> + return 0;
>> +}
>> +
>> +static void
>> +hibmc_ttm_global_release(struct hibmc_drm_device *hibmc)
>> +{
>> + if (!hibmc->ttm.mem_global_ref.release)
>
> Are you actually hitting this condition? This seems like it's papering
> over something else.
it was also delivered from others, i looked at the xxx_ttm_global_init
function, 'mem_global_ref.release' is assigned unconditionally, so i
think this condition never be hit, it may be hit when release twice,
but this won't take place in my driver.
>
>> + return;
>> +
>> + drm_global_item_unref(&hibmc->ttm.bo_global_ref.ref);
>> + drm_global_item_unref(&hibmc->ttm.mem_global_ref);
>> + hibmc->ttm.mem_global_ref.release = NULL;
>> +}
>> +
>> +static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo)
>> +{
>> + struct hibmc_bo *bo;
>> +
>> + bo = container_of(tbo, struct hibmc_bo, bo);
>
> nit: No need to split this into a separate line.
agreed, thanks.
>
>> +
>> + drm_gem_object_release(&bo->gem);
>> + kfree(bo);
>> +}
>> +
>> +static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo)
>> +{
>> + if (bo->destroy == &hibmc_bo_ttm_destroy)
>> + return true;
>> + return false;
>
> return bo->destroy == &hibmc_bo_ttm_destroy;
looks better to me.
>
>> +}
>> +
>> +static int
>> +hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
>> + struct ttm_mem_type_manager *man)
>> +{
>> + switch (type) {
>> + case TTM_PL_SYSTEM:
>> + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
>> + man->available_caching = TTM_PL_MASK_CACHING;
>> + man->default_caching = TTM_PL_FLAG_CACHED;
>> + break;
>> + case TTM_PL_VRAM:
>> + man->func = &ttm_bo_manager_func;
>> + man->flags = TTM_MEMTYPE_FLAG_FIXED |
>> + TTM_MEMTYPE_FLAG_MAPPABLE;
>> + man->available_caching = TTM_PL_FLAG_UNCACHED |
>> + TTM_PL_FLAG_WC;
>> + man->default_caching = TTM_PL_FLAG_WC;
>> + break;
>> + default:
>> + DRM_ERROR("Unsupported memory type %u\n", type);
>> + return -EINVAL;
>> + }
>> + return 0;
>> +}
>> +
>> +void hibmc_ttm_placement(struct hibmc_bo *bo, int domain)
>> +{
>> + u32 c = 0;
>
> Can you please use a more descriptive name than 'c'?
ok, will do that.
>
>> + u32 i;
>> +
>> + bo->placement.placement = bo->placements;
>> + bo->placement.busy_placement = bo->placements;
>> + if (domain & TTM_PL_FLAG_VRAM)
>> + bo->placements[c++].flags = TTM_PL_FLAG_WC |
>> + TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
>
> nit: you're alignment is off here and below
is it correct?
if (domain & TTM_PL_FLAG_VRAM)
bo->placements[c++].flags = TTM_PL_FLAG_WC |
TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
if (domain & TTM_PL_FLAG_SYSTEM)
bo->placements[c++].flags = TTM_PL_MASK_CACHING |
TTM_PL_FLAG_SYSTEM;
if (!c)
bo->placements[c++].flags = TTM_PL_MASK_CACHING |
TTM_PL_FLAG_SYSTEM;
>
>> + if (domain & TTM_PL_FLAG_SYSTEM)
>> + bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>> + TTM_PL_FLAG_SYSTEM;
>> + if (!c)
>> + bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>> + TTM_PL_FLAG_SYSTEM;
>> +
>> + bo->placement.num_placement = c;
>> + bo->placement.num_busy_placement = c;
>> + for (i = 0; i < c; ++i) {
>
> nit: we tend towards post-increment in kernel
agreed, thanks.
>
>> + bo->placements[i].fpfn = 0;
>> + bo->placements[i].lpfn = 0;
>> + }
>> +}
>> +
>> +static void
>> +hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
>> +{
>> + struct hibmc_bo *hibmcbo = hibmc_bo(bo);
>> +
>> + if (!hibmc_ttm_bo_is_hibmc_bo(bo))
>> + return;
>> +
>> + hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM);
>> + *pl = hibmcbo->placement;
>> +}
>> +
>> +static int hibmc_bo_verify_access(struct ttm_buffer_object *bo,
>> + struct file *filp)
>> +{
>> + struct hibmc_bo *hibmcbo = hibmc_bo(bo);
>> +
>> + return drm_vma_node_verify_access(&hibmcbo->gem.vma_node,
>> + filp->private_data);
>> +}
>> +
>> +static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
>> + struct ttm_mem_reg *mem)
>> +{
>> + struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
>> + struct hibmc_drm_device *hibmc = hibmc_bdev(bdev);
>> +
>> + mem->bus.addr = NULL;
>> + mem->bus.offset = 0;
>> + mem->bus.size = mem->num_pages << PAGE_SHIFT;
>> + mem->bus.base = 0;
>> + mem->bus.is_iomem = false;
>> + if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
>> + return -EINVAL;
>> + switch (mem->mem_type) {
>> + case TTM_PL_SYSTEM:
>> + /* system memory */
>> + return 0;
>> + case TTM_PL_VRAM:
>> + mem->bus.offset = mem->start << PAGE_SHIFT;
>> + mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0);
>> + mem->bus.is_iomem = true;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> + return 0;
>> +}
>> +
>> +static void hibmc_ttm_io_mem_free(struct ttm_bo_device *bdev,
>> + struct ttm_mem_reg *mem)
>> +{
>> +}
>
> No need to stub this, the caller does a NULL-check before invoking
will delete it, thanks.
>
>> +
>> +static void hibmc_ttm_backend_destroy(struct ttm_tt *tt)
>> +{
>> + ttm_tt_fini(tt);
>> + kfree(tt);
>> +}
>> +
>> +static struct ttm_backend_func hibmc_tt_backend_func = {
>> + .destroy = &hibmc_ttm_backend_destroy,
>> +};
>> +
>> +static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_bo_device *bdev,
>> + unsigned long size,
>> + u32 page_flags,
>> + struct page *dummy_read_page)
>> +{
>> + struct ttm_tt *tt;
>> +
>> + tt = kzalloc(sizeof(*tt), GFP_KERNEL);
>> + if (!tt)
>
> Print error
ok, will do that, thanks.
>
>> + return NULL;
>> + tt->func = &hibmc_tt_backend_func;
>> + if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
>
> Here too?
ditto
>
>> + kfree(tt);
>> + return NULL;
>> + }
>> + return tt;
>> +}
>> +
>> +static int hibmc_ttm_tt_populate(struct ttm_tt *ttm)
>> +{
>> + return ttm_pool_populate(ttm);
>> +}
>> +
>> +static void hibmc_ttm_tt_unpopulate(struct ttm_tt *ttm)
>> +{
>> + ttm_pool_unpopulate(ttm);
>> +}
>> +
>> +struct ttm_bo_driver hibmc_bo_driver = {
>> + .ttm_tt_create = hibmc_ttm_tt_create,
>> + .ttm_tt_populate = hibmc_ttm_tt_populate,
>> + .ttm_tt_unpopulate = hibmc_ttm_tt_unpopulate,
>> + .init_mem_type = hibmc_bo_init_mem_type,
>> + .evict_flags = hibmc_bo_evict_flags,
>> + .move = NULL,
>> + .verify_access = hibmc_bo_verify_access,
>> + .io_mem_reserve = &hibmc_ttm_io_mem_reserve,
>> + .io_mem_free = &hibmc_ttm_io_mem_free,
>> + .lru_tail = &ttm_bo_default_lru_tail,
>> + .swap_lru_tail = &ttm_bo_default_swap_lru_tail,
>> +};
>> +
>> +int hibmc_mm_init(struct hibmc_drm_device *hibmc)
>> +{
>> + int ret;
>> + struct drm_device *dev = hibmc->dev;
>> + struct ttm_bo_device *bdev = &hibmc->ttm.bdev;
>> +
>> + ret = hibmc_ttm_global_init(hibmc);
>> + if (ret)
>> + return ret;
>> +
>> + ret = ttm_bo_device_init(&hibmc->ttm.bdev,
>> + hibmc->ttm.bo_global_ref.ref.object,
>> + &hibmc_bo_driver,
>> + dev->anon_inode->i_mapping,
>> + DRM_FILE_PAGE_OFFSET,
>> + true);
>> + if (ret) {
>
> Call hibmc_ttm_global_release here?
agreed, thanks for pointing it out.
>
>> + DRM_ERROR("Error initialising bo driver; %d\n", ret);
>> + return ret;
>> + }
>> +
>> + ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
>> + hibmc->fb_size >> PAGE_SHIFT);
>> + if (ret) {
>
> Clean up here as well?
ditto
>
>> + DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
>> + return ret;
>> + }
>> +
>> + hibmc->mm_inited = true;
>> + return 0;
>> +}
>> +
>> +void hibmc_mm_fini(struct hibmc_drm_device *hibmc)
>> +{
>> + if (!hibmc->mm_inited)
>> + return;
>> +
>> + ttm_bo_device_release(&hibmc->ttm.bdev);
>> + hibmc_ttm_global_release(hibmc);
>> + hibmc->mm_inited = false;
>> +}
>> +
>> +int hibmc_bo_create(struct drm_device *dev, int size, int align,
>> + u32 flags, struct hibmc_bo **phibmcbo)
>> +{
>> + struct hibmc_drm_device *hibmc = dev->dev_private;
>> + struct hibmc_bo *hibmcbo;
>> + size_t acc_size;
>> + int ret;
>> +
>> + hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL);
>> + if (!hibmcbo)
>> + return -ENOMEM;
>> +
>> + ret = drm_gem_object_init(dev, &hibmcbo->gem, size);
>> + if (ret) {
>> + kfree(hibmcbo);
>> + return ret;
>> + }
>> +
>> + hibmcbo->bo.bdev = &hibmc->ttm.bdev;
>> +
>> + hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
>> +
>> + acc_size = ttm_bo_dma_acc_size(&hibmc->ttm.bdev, size,
>> + sizeof(struct hibmc_bo));
>> +
>> + ret = ttm_bo_init(&hibmc->ttm.bdev, &hibmcbo->bo, size,
>> + ttm_bo_type_device, &hibmcbo->placement,
>> + align >> PAGE_SHIFT, false, NULL, acc_size,
>> + NULL, NULL, hibmc_bo_ttm_destroy);
>> + if (ret)
>
> Missing hibmcbo clean up here
i looked at all other ttm drivers and all of them return directly when ttm_bo_init
failed, however, i think it is better to clean up here, should i call
hibmc_bo_unref(&hibmc_bo) here ?
>
>> + return ret;
>> +
>> + *phibmcbo = hibmcbo;
>> + return 0;
>> +}
>> +
>> +static inline u64 hibmc_bo_gpu_offset(struct hibmc_bo *bo)
>> +{
>> + return bo->bo.offset;
>> +}
>
> I don't think this function provides any value
do you nean i use bo->bo.offset instead of calling hibmc_bo_gpu_offset()?
>
>> +
>> +int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr)
>> +{
>> + int i, ret;
>> +
>> + if (bo->pin_count) {
>> + bo->pin_count++;
>> + if (gpu_addr)
>> + *gpu_addr = hibmc_bo_gpu_offset(bo);
>
> Are you missing a return here?
Thanks for pointing it out!
>
>> + }
>> +
>> + hibmc_ttm_placement(bo, pl_flag);
>> + for (i = 0; i < bo->placement.num_placement; i++)
>> + bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
>> + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
>> + if (ret)
>> + return ret;
>> +
>> + bo->pin_count = 1;
>> + if (gpu_addr)
>> + *gpu_addr = hibmc_bo_gpu_offset(bo);
>> + return 0;
>> +}
>> +
>> +int hibmc_bo_push_sysram(struct hibmc_bo *bo)
>> +{
>> + int i, ret;
>> +
>> + if (!bo->pin_count) {
>> + DRM_ERROR("unpin bad %p\n", bo);
>> + return 0;
>> + }
>> + bo->pin_count--;
>> + if (bo->pin_count)
>> + return 0;
>> +
>> + if (bo->kmap.virtual)
>
> ttm_bo_kunmap already does this check so you don't have to
agreed. will remove this condition.
>
>> + ttm_bo_kunmap(&bo->kmap);
>> +
>> + hibmc_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
>> + for (i = 0; i < bo->placement.num_placement ; i++)
>> + bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
>> +
>> + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
>> + if (ret) {
>> + DRM_ERROR("pushing to VRAM failed\n");
>
> Print ret
ok, thanks.
>
>> + return ret;
>> + }
>> + return 0;
>> +}
>> +
>> +int hibmc_mmap(struct file *filp, struct vm_area_struct *vma)
>> +{
>> + struct drm_file *file_priv;
>> + struct hibmc_drm_device *hibmc;
>> +
>> + if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
>> + return -EINVAL;
>> +
>> + file_priv = filp->private_data;
>> + hibmc = file_priv->minor->dev->dev_private;
>> + return ttm_bo_mmap(filp, vma, &hibmc->ttm.bdev);
>> +}
>> +
>> +int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
>> + struct drm_gem_object **obj)
>> +{
>> + struct hibmc_bo *hibmcbo;
>> + int ret;
>> +
>> + *obj = NULL;
>> +
>> + size = PAGE_ALIGN(size);
>> + if (size == 0)
>
> Print error
ditto
>
>> + return -EINVAL;
>> +
>> + ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo);
>> + if (ret) {
>> + if (ret != -ERESTARTSYS)
>> + DRM_ERROR("failed to allocate GEM object\n");
>
> Print ret
ditto
>
>> + return ret;
>> + }
>> + *obj = &hibmcbo->gem;
>> + return 0;
>> +}
>> +
>> +int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
>> + struct drm_mode_create_dumb *args)
>> +{
>> + struct drm_gem_object *gobj;
>> + u32 handle;
>> + int ret;
>> +
>> + args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 16);
>
> What's up with the bpp + 7 here? Perhaps you're looking for DIV_ROUND_UP?
Yes, that sounds sane.
>
>
>> + args->size = args->pitch * args->height;
>> +
>> + ret = hibmc_gem_create(dev, args->size, false,
>> + &gobj);
>> + if (ret)
>> + return ret;
>> +
>> + ret = drm_gem_handle_create(file, gobj, &handle);
>> + drm_gem_object_unreference_unlocked(gobj);
>> + if (ret)
>
> Print error here
agreed.
>
>> + return ret;
>> +
>> + args->handle = handle;
>> + return 0;
>> +}
>> +
>> +static void hibmc_bo_unref(struct hibmc_bo **bo)
>> +{
>> + struct ttm_buffer_object *tbo;
>> +
>> + if ((*bo) == NULL)
>> + return;
>> +
>> + tbo = &((*bo)->bo);
>> + ttm_bo_unref(&tbo);
>> + *bo = NULL;
>> +}
>> +
>> +void hibmc_gem_free_object(struct drm_gem_object *obj)
>> +{
>> + struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj);
>> +
>> + hibmc_bo_unref(&hibmcbo);
>> +}
>> +
>> +static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo)
>> +{
>> + return drm_vma_node_offset_addr(&bo->bo.vma_node);
>> +}
>> +
>> +int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
>> + u32 handle, u64 *offset)
>> +{
>> + struct drm_gem_object *obj;
>> + struct hibmc_bo *bo;
>> +
>> + obj = drm_gem_object_lookup(file, handle);
>> + if (!obj)
>> + return -ENOENT;
>> +
>> + bo = gem_to_hibmc_bo(obj);
>> + *offset = hibmc_bo_mmap_offset(bo);
>> +
>> + drm_gem_object_unreference_unlocked(obj);
>> + return 0;
>> +}
Regards,
Rongrong.
>> --
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> _______________________________________________
> linuxarm mailing list
> linuxarm at huawei.com
> http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm
>
> .
>
^ permalink raw reply
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