^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Epson HWA742 LCD controller driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004-2005 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Authors: Juha Yrjölä <juha.yrjola@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Imre Deak <imre.deak@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * YUV support: Jussi Laako <jussi.laako@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "omapfb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define HWA742_REV_CODE_REG 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define HWA742_CONFIG_REG 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define HWA742_PLL_DIV_REG 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define HWA742_PLL_0_REG 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define HWA742_PLL_1_REG 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define HWA742_PLL_2_REG 0xa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define HWA742_PLL_3_REG 0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define HWA742_PLL_4_REG 0xe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define HWA742_CLK_SRC_REG 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define HWA742_PANEL_TYPE_REG 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define HWA742_H_DISP_REG 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define HWA742_H_NDP_REG 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define HWA742_V_DISP_1_REG 0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define HWA742_V_DISP_2_REG 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define HWA742_V_NDP_REG 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define HWA742_HS_W_REG 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define HWA742_HP_S_REG 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define HWA742_VS_W_REG 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define HWA742_VP_S_REG 0x26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define HWA742_PCLK_POL_REG 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define HWA742_INPUT_MODE_REG 0x2a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define HWA742_TRANSL_MODE_REG1 0x2e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define HWA742_DISP_MODE_REG 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define HWA742_WINDOW_TYPE 0x36
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define HWA742_WINDOW_X_START_0 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define HWA742_WINDOW_X_START_1 0x3a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define HWA742_WINDOW_Y_START_0 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define HWA742_WINDOW_Y_START_1 0x3e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define HWA742_WINDOW_X_END_0 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define HWA742_WINDOW_X_END_1 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define HWA742_WINDOW_Y_END_0 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define HWA742_WINDOW_Y_END_1 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define HWA742_MEMORY_WRITE_LSB 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define HWA742_MEMORY_WRITE_MSB 0x49
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define HWA742_MEMORY_READ_0 0x4a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define HWA742_MEMORY_READ_1 0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define HWA742_MEMORY_READ_2 0x4e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define HWA742_POWER_SAVE 0x56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define HWA742_NDP_CTRL 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define HWA742_AUTO_UPDATE_TIME (HZ / 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Reserve 4 request slots for requests in irq context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define REQ_POOL_SIZE 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define IRQ_REQ_POOL_SIZE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define REQ_FROM_IRQ_POOL 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define REQ_COMPLETE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define REQ_PENDING 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct update_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int x, y, width, height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int color_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct hwa742_request {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct list_head entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int (*handler)(struct hwa742_request *req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) void (*complete)(void *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) void *complete_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct update_param update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct completion *sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) } par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) enum omapfb_update_mode update_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) enum omapfb_update_mode update_mode_before_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct timer_list auto_update_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int stop_auto_update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct omapfb_update_window auto_update_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned te_connected:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned vsync_only:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct hwa742_request req_pool[REQ_POOL_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct list_head pending_req_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct list_head free_req_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct semaphore req_sema;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) spinlock_t req_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct extif_timings reg_timings, lut_timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int prev_color_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int prev_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int window_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u32 max_transmit_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u32 extif_clk_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned long pix_tx_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned long line_upd_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct omapfb_device *fbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct lcd_ctrl_extif *extif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) const struct lcd_ctrl *int_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct clk *sys_ck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) } hwa742;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct lcd_ctrl hwa742_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static u8 hwa742_read_reg(u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) hwa742.extif->set_bits_per_cycle(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) hwa742.extif->write_command(®, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) hwa742.extif->read_data(&data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static void hwa742_write_reg(u8 reg, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hwa742.extif->set_bits_per_cycle(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) hwa742.extif->write_command(®, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) hwa742.extif->write_data(&data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static void set_window_regs(int x_start, int y_start, int x_end, int y_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u8 tmp[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) x_end--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) y_end--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tmp[0] = x_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) tmp[1] = x_start >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) tmp[2] = y_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) tmp[3] = y_start >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) tmp[4] = x_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) tmp[5] = x_end >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tmp[6] = y_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) tmp[7] = y_end >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) hwa742.extif->set_bits_per_cycle(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) cmd = HWA742_WINDOW_X_START_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) hwa742.extif->write_command(&cmd, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) hwa742.extif->write_data(tmp, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void set_format_regs(int conv, int transl, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #ifdef VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) hwa742.window_type = (hwa742.window_type & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #ifdef VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void enable_tearsync(int y, int width, int height, int screen_height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int force_vsync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u8 b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) b = hwa742_read_reg(HWA742_NDP_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) b |= 1 << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) hwa742_write_reg(HWA742_NDP_CTRL, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (likely(hwa742.vsync_only || force_vsync)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) hwa742.extif->enable_tearsync(1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (width * hwa742.pix_tx_time < hwa742.line_upd_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) hwa742.extif->enable_tearsync(1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if ((width * hwa742.pix_tx_time / 1000) * height <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) (y + height) * (hwa742.line_upd_time / 1000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) hwa742.extif->enable_tearsync(1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) hwa742.extif->enable_tearsync(1, y + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void disable_tearsync(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u8 b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) hwa742.extif->enable_tearsync(0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) b = hwa742_read_reg(HWA742_NDP_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) b &= ~(1 << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) hwa742_write_reg(HWA742_NDP_CTRL, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static inline struct hwa742_request *alloc_req(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct hwa742_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int req_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (!in_interrupt())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) down(&hwa742.req_sema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) req_flags = REQ_FROM_IRQ_POOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) spin_lock_irqsave(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) BUG_ON(list_empty(&hwa742.free_req_list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) req = list_entry(hwa742.free_req_list.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct hwa742_request, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) list_del(&req->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) spin_unlock_irqrestore(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) INIT_LIST_HEAD(&req->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) req->flags = req_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static inline void free_req(struct hwa742_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) spin_lock_irqsave(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) list_move(&req->entry, &hwa742.free_req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!(req->flags & REQ_FROM_IRQ_POOL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) up(&hwa742.req_sema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) spin_unlock_irqrestore(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static void process_pending_requests(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) spin_lock_irqsave(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) while (!list_empty(&hwa742.pending_req_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct hwa742_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) void (*complete)(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) void *complete_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) req = list_entry(hwa742.pending_req_list.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct hwa742_request, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) spin_unlock_irqrestore(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (req->handler(req) == REQ_PENDING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) complete = req->complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) complete_data = req->complete_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) free_req(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) complete(complete_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) spin_lock_irqsave(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) spin_unlock_irqrestore(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static void submit_req_list(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int process = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) spin_lock_irqsave(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (likely(!list_empty(&hwa742.pending_req_list)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) process = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) list_splice_init(head, hwa742.pending_req_list.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) spin_unlock_irqrestore(&hwa742.req_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) process_pending_requests();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static void request_complete(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct hwa742_request *req = (struct hwa742_request *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) void (*complete)(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) void *complete_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) complete = req->complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) complete_data = req->complete_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) free_req(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) complete(complete_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) process_pending_requests();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static int send_frame_handler(struct hwa742_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct update_param *par = &req->par.update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int x = par->x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int y = par->y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int w = par->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) int h = par->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int conv, transl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) int color_mode = par->color_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int flags = par->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int scr_width = hwa742.fbdev->panel->x_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int scr_height = hwa742.fbdev->panel->y_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) #ifdef VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) "color_mode %d flags %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) x, y, w, h, scr_width, color_mode, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) switch (color_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case OMAPFB_COLOR_YUV422:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) conv = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) transl = 0x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) case OMAPFB_COLOR_YUV420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) bpp = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) conv = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) transl = 0x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case OMAPFB_COLOR_RGB565:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) conv = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) transl = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (hwa742.prev_flags != flags ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) hwa742.prev_color_mode != color_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) set_format_regs(conv, transl, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) hwa742.prev_color_mode = color_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) hwa742.prev_flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) flags = req->par.update.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) enable_tearsync(y, scr_width, h, scr_height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) disable_tearsync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) set_window_regs(x, y, x + w, y + h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) offset = (scr_width * y + x) * bpp / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) color_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) hwa742.extif->set_bits_per_cycle(16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) hwa742.extif->transfer_area(w, h, request_complete, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return REQ_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static void send_frame_complete(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) #define ADD_PREQ(_x, _y, _w, _h) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) req = alloc_req(); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) req->handler = send_frame_handler; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) req->complete = send_frame_complete; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) req->par.update.x = _x; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) req->par.update.y = _y; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) req->par.update.width = _w; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) req->par.update.height = _h; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) req->par.update.color_mode = color_mode;\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) req->par.update.flags = flags; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) list_add_tail(&req->entry, req_head); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static void create_req_list(struct omapfb_update_window *win,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct list_head *req_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct hwa742_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int x = win->x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int y = win->y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int width = win->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int height = win->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) int color_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) flags = win->format & ~OMAPFB_FORMAT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) color_mode = win->format & OMAPFB_FORMAT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (x & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ADD_PREQ(x, y, 1, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) width--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) x++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (width & ~1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) unsigned int xspan = width & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) unsigned int ystart = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) unsigned int yspan = height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (xspan * height * 2 > hwa742.max_transmit_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) yspan = hwa742.max_transmit_size / (xspan * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ADD_PREQ(x, ystart, xspan, yspan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ystart += yspan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) yspan = height - yspan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ADD_PREQ(x, ystart, xspan, yspan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) x += xspan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) width -= xspan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ADD_PREQ(x, y, 1, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static void auto_update_complete(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (!hwa742.stop_auto_update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) mod_timer(&hwa742.auto_update_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) jiffies + HWA742_AUTO_UPDATE_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static void hwa742_update_window_auto(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) LIST_HEAD(req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct hwa742_request *last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) create_req_list(&hwa742.auto_update_window, &req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) last = list_entry(req_list.prev, struct hwa742_request, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) last->complete = auto_update_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) last->complete_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) submit_req_list(&req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int hwa742_update_window_async(struct fb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct omapfb_update_window *win,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) void (*complete_callback)(void *arg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) void *complete_callback_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) LIST_HEAD(req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct hwa742_request *last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) dev_dbg(hwa742.fbdev->dev, "invalid update mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) r = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (unlikely(win->format &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) dev_dbg(hwa742.fbdev->dev, "invalid window flag\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) r = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) create_req_list(win, &req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) last = list_entry(req_list.prev, struct hwa742_request, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) last->complete = complete_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) last->complete_data = (void *)complete_callback_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) submit_req_list(&req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) EXPORT_SYMBOL(hwa742_update_window_async);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static int hwa742_setup_plane(int plane, int channel_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) unsigned long offset, int screen_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) int pos_x, int pos_y, int width, int height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) int color_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (plane != OMAPFB_PLANE_GFX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) channel_out != OMAPFB_CHANNEL_OUT_LCD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int hwa742_enable_plane(int plane, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (plane != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) hwa742.int_ctrl->enable_plane(plane, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static int sync_handler(struct hwa742_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) complete(req->par.sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return REQ_COMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static void hwa742_sync(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) LIST_HEAD(req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct hwa742_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct completion comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) req = alloc_req();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) req->handler = sync_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) req->complete = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) init_completion(&comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) req->par.sync = ∁
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) list_add(&req->entry, &req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) submit_req_list(&req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) wait_for_completion(&comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static void hwa742_bind_client(struct omapfb_notifier_block *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int hwa742_set_update_mode(enum omapfb_update_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) mode != OMAPFB_UPDATE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (mode == hwa742.update_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) switch (hwa742.update_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) case OMAPFB_MANUAL_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) case OMAPFB_AUTO_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) hwa742.stop_auto_update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) del_timer_sync(&hwa742.auto_update_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) case OMAPFB_UPDATE_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) hwa742.update_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) hwa742_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) hwa742.stop_auto_update = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) case OMAPFB_MANUAL_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) case OMAPFB_AUTO_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) hwa742_update_window_auto(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) case OMAPFB_UPDATE_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static enum omapfb_update_mode hwa742_get_update_mode(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return hwa742.update_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static unsigned long round_to_extif_ticks(unsigned long ps, int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) int bus_tick = hwa742.extif_clk_period * div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return (ps + bus_tick - 1) / bus_tick * bus_tick;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static int calc_reg_timing(unsigned long sysclk, int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct extif_timings *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) unsigned long systim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * AccessTime 2 ns + 12.2 ns (regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * WEOffTime = WEOnTime + 1 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * REOffTime = REOnTime + 16 ns (regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * CSOffTime = REOffTime + 1 ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * ReadCycle = 2ns + 2*SYSCLK (regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * WriteCycle = 2*SYSCLK + 2 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * CSPulseWidth = 10 ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) systim = 1000000000 / (sysclk / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) t = &hwa742.reg_timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) memset(t, 0, sizeof(*t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) t->clk_div = div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) t->cs_on_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (t->we_cycle_time < t->we_off_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) t->we_cycle_time = t->we_off_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (t->re_cycle_time < t->re_off_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) t->re_cycle_time = t->re_off_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) t->cs_pulse_width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) t->we_on_time, t->we_off_time, t->re_cycle_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) t->we_cycle_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) t->access_time, t->cs_pulse_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return hwa742.extif->convert_timings(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int calc_lut_timing(unsigned long sysclk, int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct extif_timings *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) unsigned long systim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * WEOffTime = WEOnTime + 1 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * CSOffTime = REOffTime + 1 ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * WriteCycle = 2*SYSCLK + 2 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * CSPulseWidth = 10 ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) systim = 1000000000 / (sysclk / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) t = &hwa742.lut_timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) memset(t, 0, sizeof(*t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) t->clk_div = div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) t->cs_on_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 26000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 26000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (t->we_cycle_time < t->we_off_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) t->we_cycle_time = t->we_off_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (t->re_cycle_time < t->re_off_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) t->re_cycle_time = t->re_off_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) t->cs_pulse_width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) t->we_on_time, t->we_off_time, t->re_cycle_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) t->we_cycle_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) t->access_time, t->cs_pulse_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return hwa742.extif->convert_timings(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int max_clk_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) for (div = 1; div < max_clk_div; div++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (calc_reg_timing(sysclk, div) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (div >= max_clk_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) *extif_mem_div = div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) for (div = 1; div < max_clk_div; div++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (calc_lut_timing(sysclk, div) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (div >= max_clk_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) dev_err(hwa742.fbdev->dev, "can't setup timings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static void calc_hwa742_clk_rates(unsigned long ext_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) unsigned long *sys_clk, unsigned long *pix_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int pix_clk_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) int sys_div = 0, sys_mul = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int pix_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if ((pix_clk_src & (0x3 << 1)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* Source is the PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) *sys_clk = ext_clk * sys_mul / sys_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) } else /* else source is ext clk, or oscillator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) *sys_clk = ext_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) *pix_clk = *sys_clk / pix_div; /* HZ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) dev_dbg(hwa742.fbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) *sys_clk, *pix_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static int setup_tearsync(unsigned long pix_clk, int extif_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) int hdisp, vdisp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) int hndp, vndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int hsw, vsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) int hs, vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) int hs_pol_inv, vs_pol_inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) int use_hsvs, use_ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) u8 b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) hsw = hwa742_read_reg(HWA742_HS_W_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) vsw = hwa742_read_reg(HWA742_VS_W_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) hs_pol_inv = !(hsw & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) vs_pol_inv = !(vsw & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) hsw = hsw & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) vsw = vsw & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) ((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) vndp = hwa742_read_reg(HWA742_V_NDP_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* time to transfer one pixel (16bpp) in ps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (hwa742.extif->get_max_tx_rate != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * The external interface might have a rate limitation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * if so, we have to maximize our transfer rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) unsigned long min_tx_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) max_tx_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (hwa742.pix_tx_time < min_tx_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) hwa742.pix_tx_time = min_tx_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* time to update one line in ps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) hwa742.line_upd_time *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * transfer speed too low, we might have to use both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * HS and VS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) use_hsvs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* decent transfer speed, we'll always use only VS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) use_hsvs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * HS or'ed with VS doesn't work, use the active high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * TE signal based on HNDP / VNDP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) use_ndp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) hs_pol_inv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) vs_pol_inv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) hs = hndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) vs = vndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * Use HS or'ed with VS as a TE signal if both are needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * or VNDP if only vsync is needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) use_ndp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) hs = hsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) vs = vsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (!use_hsvs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) hs_pol_inv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) vs_pol_inv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) hs = hs * 1000000 / (pix_clk / 1000); /* ps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) hs *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) vs *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (vs <= hs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return -EDOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* set VS to 120% of HS to minimize VS detection time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) vs = hs * 12 / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* minimize HS too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) hs = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) b = hwa742_read_reg(HWA742_NDP_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) b &= ~0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) b |= use_hsvs ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) b |= (use_ndp && use_hsvs) ? 0 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) hwa742_write_reg(HWA742_NDP_CTRL, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) hwa742.vsync_only = !use_hsvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) dev_dbg(hwa742.fbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) dev_dbg(hwa742.fbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) "hs %d ps vs %d ps mode %d vsync_only %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) hs, vs, (b & 0x3), !use_hsvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return hwa742.extif->setup_tearsync(1, hs, vs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) hs_pol_inv, vs_pol_inv, extif_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static void hwa742_get_caps(int plane, struct omapfb_caps *caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) hwa742.int_ctrl->get_caps(plane, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (hwa742.te_connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) (1 << OMAPFB_COLOR_YUV420);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) static void hwa742_suspend(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) hwa742.update_mode_before_suspend = hwa742.update_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /* Enable sleep mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) clk_disable(hwa742.sys_ck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static void hwa742_resume(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) clk_enable(hwa742.sys_ck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* Disable sleep mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) hwa742_write_reg(HWA742_POWER_SAVE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* Loop until PLL output is stabilized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) schedule_timeout(msecs_to_jiffies(5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) hwa742_set_update_mode(hwa742.update_mode_before_suspend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct omapfb_mem_desc *req_vram)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) int r = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) u8 rev, conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) unsigned long ext_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) unsigned long sys_clk, pix_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) int extif_mem_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct omapfb_platform_data *omapfb_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) hwa742.fbdev = fbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) hwa742.extif = fbdev->ext_if;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) hwa742.int_ctrl = fbdev->int_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) omapfb_conf = dev_get_platdata(fbdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) spin_lock_init(&hwa742.req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if ((r = hwa742.extif->init(fbdev)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ext_clk = clk_get_rate(hwa742.sys_ck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) goto err3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) hwa742.extif->set_timings(&hwa742.reg_timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) clk_enable(hwa742.sys_ck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) goto err4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) hwa742.extif->set_timings(&hwa742.reg_timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) rev = hwa742_read_reg(HWA742_REV_CODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if ((rev & 0xfc) != 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) r = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) goto err4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) dev_err(fbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) "HWA742: controller not initialized by the bootloader\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) r = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) goto err4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) dev_err(hwa742.fbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) "HWA742: can't setup tearing synchronization\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) goto err4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) hwa742.te_connected = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) hwa742.update_mode = OMAPFB_UPDATE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) hwa742.auto_update_window.x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) hwa742.auto_update_window.y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) hwa742.auto_update_window.width = fbdev->panel->x_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) hwa742.auto_update_window.height = fbdev->panel->y_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) hwa742.auto_update_window.format = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) timer_setup(&hwa742.auto_update_timer, hwa742_update_window_auto, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) hwa742.prev_color_mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) hwa742.prev_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) hwa742.fbdev = fbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) INIT_LIST_HEAD(&hwa742.free_req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) INIT_LIST_HEAD(&hwa742.pending_req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) BUG_ON(i <= IRQ_REQ_POOL_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) conf = hwa742_read_reg(HWA742_CONFIG_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) err4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) clk_disable(hwa742.sys_ck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) err3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) hwa742.extif->cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) hwa742.int_ctrl->cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) static void hwa742_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) hwa742.extif->cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) hwa742.int_ctrl->cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) clk_disable(hwa742.sys_ck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct lcd_ctrl hwa742_ctrl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) .name = "hwa742",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) .init = hwa742_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .cleanup = hwa742_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) .bind_client = hwa742_bind_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .get_caps = hwa742_get_caps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) .set_update_mode = hwa742_set_update_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) .get_update_mode = hwa742_get_update_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) .setup_plane = hwa742_setup_plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) .enable_plane = hwa742_enable_plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) .update_window = hwa742_update_window_async,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) .sync = hwa742_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) .suspend = hwa742_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) .resume = hwa742_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)