summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev/omap/hwa742.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev/omap/hwa742.c')
-rw-r--r--drivers/video/fbdev/omap/hwa742.c72
1 files changed, 35 insertions, 37 deletions
diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c
index a4ee65b8f918..64e76e1f5388 100644
--- a/drivers/video/fbdev/omap/hwa742.c
+++ b/drivers/video/fbdev/omap/hwa742.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Epson HWA742 LCD controller driver
*
@@ -5,20 +6,6 @@
* Authors: Juha Yrjölä <juha.yrjola@nokia.com>
* Imre Deak <imre.deak@nokia.com>
* YUV support: Jussi Laako <jussi.laako@nokia.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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/mm.h>
@@ -113,6 +100,14 @@ struct {
struct hwa742_request req_pool[REQ_POOL_SIZE];
struct list_head pending_req_list;
struct list_head free_req_list;
+
+ /*
+ * @req_lock: protect request slots pool and its tracking lists
+ * @req_sema: counter; slot allocators from task contexts must
+ * push it down before acquiring a slot. This
+ * guarantees that atomic contexts will always have
+ * a minimum of IRQ_REQ_POOL_SIZE slots available.
+ */
struct semaphore req_sema;
spinlock_t req_lock;
@@ -237,13 +232,13 @@ static void disable_tearsync(void)
hwa742_write_reg(HWA742_NDP_CTRL, b);
}
-static inline struct hwa742_request *alloc_req(void)
+static inline struct hwa742_request *alloc_req(bool can_sleep)
{
unsigned long flags;
struct hwa742_request *req;
int req_flags = 0;
- if (!in_interrupt())
+ if (can_sleep)
down(&hwa742.req_sema);
else
req_flags = REQ_FROM_IRQ_POOL;
@@ -412,8 +407,8 @@ static void send_frame_complete(void *data)
hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
}
-#define ADD_PREQ(_x, _y, _w, _h) do { \
- req = alloc_req(); \
+#define ADD_PREQ(_x, _y, _w, _h, can_sleep) do {\
+ req = alloc_req(can_sleep); \
req->handler = send_frame_handler; \
req->complete = send_frame_complete; \
req->par.update.x = _x; \
@@ -426,7 +421,8 @@ static void send_frame_complete(void *data)
} while(0)
static void create_req_list(struct omapfb_update_window *win,
- struct list_head *req_head)
+ struct list_head *req_head,
+ bool can_sleep)
{
struct hwa742_request *req;
int x = win->x;
@@ -440,7 +436,7 @@ static void create_req_list(struct omapfb_update_window *win,
color_mode = win->format & OMAPFB_FORMAT_MASK;
if (x & 1) {
- ADD_PREQ(x, y, 1, height);
+ ADD_PREQ(x, y, 1, height, can_sleep);
width--;
x++;
flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
@@ -452,19 +448,19 @@ static void create_req_list(struct omapfb_update_window *win,
if (xspan * height * 2 > hwa742.max_transmit_size) {
yspan = hwa742.max_transmit_size / (xspan * 2);
- ADD_PREQ(x, ystart, xspan, yspan);
+ ADD_PREQ(x, ystart, xspan, yspan, can_sleep);
ystart += yspan;
yspan = height - yspan;
flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
}
- ADD_PREQ(x, ystart, xspan, yspan);
+ ADD_PREQ(x, ystart, xspan, yspan, can_sleep);
x += xspan;
width -= xspan;
flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
}
if (width)
- ADD_PREQ(x, y, 1, height);
+ ADD_PREQ(x, y, 1, height, can_sleep);
}
static void auto_update_complete(void *data)
@@ -474,12 +470,12 @@ static void auto_update_complete(void *data)
jiffies + HWA742_AUTO_UPDATE_TIME);
}
-static void hwa742_update_window_auto(unsigned long arg)
+static void __hwa742_update_window_auto(bool can_sleep)
{
LIST_HEAD(req_list);
struct hwa742_request *last;
- create_req_list(&hwa742.auto_update_window, &req_list);
+ create_req_list(&hwa742.auto_update_window, &req_list, can_sleep);
last = list_entry(req_list.prev, struct hwa742_request, entry);
last->complete = auto_update_complete;
@@ -488,7 +484,12 @@ static void hwa742_update_window_auto(unsigned long arg)
submit_req_list(&req_list);
}
-int hwa742_update_window_async(struct fb_info *fbi,
+static void hwa742_update_window_auto(struct timer_list *unused)
+{
+ __hwa742_update_window_auto(false);
+}
+
+static int hwa742_update_window_async(struct fb_info *fbi,
struct omapfb_update_window *win,
void (*complete_callback)(void *arg),
void *complete_callback_data)
@@ -510,7 +511,7 @@ int hwa742_update_window_async(struct fb_info *fbi,
goto out;
}
- create_req_list(win, &req_list);
+ create_req_list(win, &req_list, true);
last = list_entry(req_list.prev, struct hwa742_request, entry);
last->complete = complete_callback;
@@ -521,7 +522,6 @@ int hwa742_update_window_async(struct fb_info *fbi,
out:
return r;
}
-EXPORT_SYMBOL(hwa742_update_window_async);
static int hwa742_setup_plane(int plane, int channel_out,
unsigned long offset, int screen_width,
@@ -557,7 +557,7 @@ static void hwa742_sync(void)
struct hwa742_request *req;
struct completion comp;
- req = alloc_req();
+ req = alloc_req(true);
req->handler = sync_handler;
req->complete = NULL;
@@ -597,7 +597,7 @@ static int hwa742_set_update_mode(enum omapfb_update_mode mode)
break;
case OMAPFB_AUTO_UPDATE:
hwa742.stop_auto_update = 1;
- del_timer_sync(&hwa742.auto_update_timer);
+ timer_delete_sync(&hwa742.auto_update_timer);
break;
case OMAPFB_UPDATE_DISABLED:
break;
@@ -612,7 +612,7 @@ static int hwa742_set_update_mode(enum omapfb_update_mode mode)
omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
break;
case OMAPFB_AUTO_UPDATE:
- hwa742_update_window_auto(0);
+ __hwa742_update_window_auto(true);
break;
case OMAPFB_UPDATE_DISABLED:
break;
@@ -963,7 +963,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
goto err3;
hwa742.extif->set_timings(&hwa742.reg_timings);
- clk_enable(hwa742.sys_ck);
+ clk_prepare_enable(hwa742.sys_ck);
calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
@@ -1002,9 +1002,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
hwa742.auto_update_window.height = fbdev->panel->y_res;
hwa742.auto_update_window.format = 0;
- init_timer(&hwa742.auto_update_timer);
- hwa742.auto_update_timer.function = hwa742_update_window_auto;
- hwa742.auto_update_timer.data = 0;
+ timer_setup(&hwa742.auto_update_timer, hwa742_update_window_auto, 0);
hwa742.prev_color_mode = -1;
hwa742.prev_flags = 0;
@@ -1024,7 +1022,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
return 0;
err4:
- clk_disable(hwa742.sys_ck);
+ clk_disable_unprepare(hwa742.sys_ck);
err3:
hwa742.extif->cleanup();
err2:
@@ -1038,7 +1036,7 @@ static void hwa742_cleanup(void)
hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
hwa742.extif->cleanup();
hwa742.int_ctrl->cleanup();
- clk_disable(hwa742.sys_ck);
+ clk_disable_unprepare(hwa742.sys_ck);
}
struct lcd_ctrl hwa742_ctrl = {