summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDanny Nold <dannynold@freescale.com>2012-03-08 15:12:43 -0600
committerDanny Nold <dannynold@freescale.com>2012-03-09 09:47:40 -0600
commit442ddf797f97599dab273a6b4cc915848f2c14bb (patch)
treec472b4ebd47d72076bb9e6dfaaafdd138d20c109 /drivers
parente1be4924ca2868b773fb0a5b15b28c56d6f4a0e3 (diff)
ENGR00176504 - EPDC fb: Reduce number of PxP output buffers to 2
- Changed from one-buffer-per-LUT (up to 16 for EPDCv1.0 and 64 for EPDCv2.0) to using 2 static buffers for PxP output. This is facilitated by the switch to using a single-threaded workqueue to process each update, which guarantees that we can use just 2 buffers without clobbering concurrent updates. - One known limitation: This restricts the SNAPSHOT update scheme to only 2 concurrent updates. So if a user intends to use SNAPSHOT scheme, the EPDC_MAX_NUM_BUFFERS #define should be increased based on the desired number of allowable concurrent updates (with a corresponding penalty in static memory allocation). Signed-off-by: Danny Nold <dannynold@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/mxc/mxc_epdc_fb.c77
1 files changed, 59 insertions, 18 deletions
diff --git a/drivers/video/mxc/mxc_epdc_fb.c b/drivers/video/mxc/mxc_epdc_fb.c
index 36bb84dc1511..3d81e9151596 100644
--- a/drivers/video/mxc/mxc_epdc_fb.c
+++ b/drivers/video/mxc/mxc_epdc_fb.c
@@ -65,6 +65,7 @@
#define EPDC_V1_MAX_NUM_UPDATES 20
#define EPDC_V2_NUM_LUTS 64
#define EPDC_V2_MAX_NUM_UPDATES 64
+#define EPDC_MAX_NUM_BUFFERS 2
#define INVALID_LUT (-1)
#define DRY_RUN_NO_LUT 100
@@ -172,6 +173,10 @@ struct mxc_epdc_fb_data {
u32 *working_buffer_virt;
u32 working_buffer_phys;
u32 working_buffer_size;
+ dma_addr_t *phys_addr_updbuf;
+ void **virt_addr_updbuf;
+ u32 upd_buffer_num;
+ u32 max_num_buffers;
dma_addr_t phys_addr_copybuf; /* Phys address of copied update data */
void *virt_addr_copybuf; /* Used for PxP SW workaround */
u32 order_cnt;
@@ -2381,6 +2386,15 @@ static void epdc_submit_work_func(struct work_struct *work)
fb_data->info.var.xres_virtual *
fb_data->info.var.bits_per_pixel/8;
} else {
+ /* Select from PxP output buffers */
+ upd_data_list->phys_addr =
+ fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
+ upd_data_list->virt_addr =
+ fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
+ fb_data->upd_buffer_num++;
+ if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
+ fb_data->upd_buffer_num = 0;
+
/* Release buffer queues */
mutex_unlock(&fb_data->queue_mutex);
@@ -2630,6 +2644,9 @@ int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
}
if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
+ int count = 0;
+ struct update_data_list *plist;
+
/*
* If next update is a FULL mode update, then we must
* ensure that all pending & active updates are complete
@@ -2643,11 +2660,14 @@ int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
mutex_lock(&fb_data->queue_mutex);
}
- /*
- * Get available intermediate (PxP output) buffer to hold
- * processed update region
- */
- if (list_empty(&fb_data->upd_buf_free_list)) {
+ /* Count buffers in free buffer list */
+ list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
+ count++;
+
+ /* Use count to determine if we have enough
+ * free buffers to handle this update request */
+ if (count + fb_data->max_num_buffers
+ <= fb_data->max_num_updates) {
dev_err(fb_data->dev,
"No free intermediate buffers available.\n");
mutex_unlock(&fb_data->queue_mutex);
@@ -2732,6 +2752,15 @@ int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
*/
screen_upd_region = &upd_desc->upd_data.update_region;
+ /* Select from PxP output buffers */
+ upd_data_list->phys_addr =
+ fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
+ upd_data_list->virt_addr =
+ fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
+ fb_data->upd_buffer_num++;
+ if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
+ fb_data->upd_buffer_num = 0;
+
ret = epdc_process_update(upd_data_list, fb_data);
if (ret) {
mutex_unlock(&fb_data->pxp_mutex);
@@ -4378,11 +4407,12 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
fb_data->num_luts = EPDC_V2_NUM_LUTS;
fb_data->max_num_updates = EPDC_V2_MAX_NUM_UPDATES;
}
+ fb_data->max_num_buffers = EPDC_MAX_NUM_BUFFERS;
/*
* Initialize lists for pending updates,
* active update requests, update collisions,
- * and available update (PxP output) buffers
+ * and freely available updates.
*/
INIT_LIST_HEAD(&fb_data->upd_pending_list);
INIT_LIST_HEAD(&fb_data->upd_buf_queue);
@@ -4394,30 +4424,39 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
upd_list = kzalloc(sizeof(*upd_list), GFP_KERNEL);
if (upd_list == NULL) {
ret = -ENOMEM;
- goto out_upd_buffers;
+ goto out_upd_lists;
}
+ /* Add newly allocated buffer to free list */
+ list_add(&upd_list->list, &fb_data->upd_buf_free_list);
+ }
+
+ fb_data->virt_addr_updbuf =
+ kzalloc(sizeof(void *) * fb_data->max_num_buffers, GFP_KERNEL);
+ fb_data->phys_addr_updbuf =
+ kzalloc(sizeof(dma_addr_t) * fb_data->max_num_buffers,
+ GFP_KERNEL);
+ for (i = 0; i < fb_data->max_num_buffers; i++) {
/*
* Allocate memory for PxP output buffer.
* Each update buffer is 1 byte per pixel, and can
* be as big as the full-screen frame buffer
*/
- upd_list->virt_addr =
+ fb_data->virt_addr_updbuf[i] =
dma_alloc_coherent(fb_data->info.device, fb_data->max_pix_size,
- &upd_list->phys_addr, GFP_DMA);
- if (upd_list->virt_addr == NULL) {
- kfree(upd_list);
+ &fb_data->phys_addr_updbuf[i], GFP_DMA);
+ if (fb_data->virt_addr_updbuf[i] == NULL) {
ret = -ENOMEM;
goto out_upd_buffers;
}
- /* Add newly allocated buffer to free list */
- list_add(&upd_list->list, &fb_data->upd_buf_free_list);
-
dev_dbg(fb_data->info.device, "allocated %d bytes @ 0x%08X\n",
- fb_data->max_pix_size, upd_list->phys_addr);
+ fb_data->max_pix_size, fb_data->phys_addr_updbuf[i]);
}
+ /* Counter indicating which update buffer should be used next. */
+ fb_data->upd_buffer_num = 0;
+
/*
* Allocate memory for PxP SW workaround buffer
* These buffers are used to hold copy of the update region,
@@ -4683,12 +4722,14 @@ out_copybuffer:
fb_data->virt_addr_copybuf,
fb_data->phys_addr_copybuf);
out_upd_buffers:
+ for (i = 0; i < fb_data->max_num_buffers; i++)
+ dma_free_writecombine(&pdev->dev, fb_data->max_pix_size,
+ fb_data->virt_addr_updbuf[i],
+ fb_data->phys_addr_updbuf[i]);
+out_upd_lists:
list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list,
list) {
list_del(&plist->list);
- dma_free_writecombine(&pdev->dev, fb_data->max_pix_size,
- plist->virt_addr,
- plist->phys_addr);
kfree(plist);
}
out_dma_fb: