^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) * Copyright (C) 2008-2009 MontaVista Software Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2008-2009 Texas Instruments Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Based on the LCD driver for TI Avalanche processors written by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Ajay Singh and Shalom Hai.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/lcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <video/da8xx-fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define DRIVER_NAME "da8xx_lcdc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define LCD_VERSION_1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define LCD_VERSION_2 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* LCD Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define LCD_END_OF_FRAME1 BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define LCD_END_OF_FRAME0 BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define LCD_PL_LOAD_DONE BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define LCD_FIFO_UNDERFLOW BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define LCD_SYNC_LOST BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define LCD_FRAME_DONE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* LCD DMA Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define LCD_DMA_BURST_SIZE(x) ((x) << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define LCD_DMA_BURST_1 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define LCD_DMA_BURST_2 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define LCD_DMA_BURST_4 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define LCD_DMA_BURST_8 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define LCD_DMA_BURST_16 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define LCD_V1_END_OF_FRAME_INT_ENA BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* LCD Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define LCD_CLK_DIVISOR(x) ((x) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define LCD_RASTER_MODE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* LCD Raster Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define LCD_PALETTE_LOAD_MODE(x) ((x) << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define PALETTE_AND_DATA 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define PALETTE_ONLY 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define DATA_ONLY 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define LCD_MONO_8BIT_MODE BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define LCD_RASTER_ORDER BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define LCD_TFT_MODE BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define LCD_V1_UNDERFLOW_INT_ENA BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define LCD_V2_UNDERFLOW_INT_ENA BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define LCD_V1_PL_INT_ENA BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define LCD_V2_PL_INT_ENA BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define LCD_MONOCHROME_MODE BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define LCD_RASTER_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define LCD_TFT_ALT_ENABLE BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define LCD_STN_565_ENABLE BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define LCD_V2_DMA_CLK_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define LCD_V2_LIDD_CLK_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define LCD_V2_CORE_CLK_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define LCD_V2_LPP_B10 26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define LCD_V2_TFT_24BPP_MODE BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define LCD_V2_TFT_24BPP_UNPACK BIT(26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* LCD Raster Timing 2 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define LCD_SYNC_CTRL BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define LCD_SYNC_EDGE BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define LCD_INVERT_PIXEL_CLOCK BIT(22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define LCD_INVERT_LINE_CLOCK BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define LCD_INVERT_FRAME_CLOCK BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* LCD Block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define LCD_PID_REG 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define LCD_CTRL_REG 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define LCD_STAT_REG 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define LCD_RASTER_CTRL_REG 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define LCD_RASTER_TIMING_0_REG 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define LCD_RASTER_TIMING_1_REG 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define LCD_RASTER_TIMING_2_REG 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define LCD_DMA_CTRL_REG 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Interrupt Registers available only in Version 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define LCD_RAW_STAT_REG 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define LCD_MASKED_STAT_REG 0x5c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define LCD_INT_ENABLE_SET_REG 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define LCD_INT_ENABLE_CLR_REG 0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define LCD_END_OF_INT_IND_REG 0x68
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Clock registers available only on Version 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define LCD_CLK_ENABLE_REG 0x6c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define LCD_CLK_RESET_REG 0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define LCD_CLK_MAIN_RESET BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define LCD_NUM_BUFFERS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define PALETTE_SIZE 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define CLK_MIN_DIV 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define CLK_MAX_DIV 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void __iomem *da8xx_fb_reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static unsigned int lcd_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static irq_handler_t lcdc_irq_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static wait_queue_head_t frame_done_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int frame_done_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static unsigned int lcdc_read(unsigned int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static void lcdc_write(unsigned int val, unsigned int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) __raw_writel(val, da8xx_fb_reg_base + (addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct da8xx_fb_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) dma_addr_t p_palette_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned char *v_palette_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dma_addr_t vram_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) unsigned long vram_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) void *vram_virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned int dma_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned int dma_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct clk *lcdc_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned int palette_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int blank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) wait_queue_head_t vsync_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int vsync_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int vsync_timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) spinlock_t lock_for_chan_update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * LCDC has 2 ping pong DMA channels, channel 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * and channel 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned int which_dma_channel_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct notifier_block freq_transition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int lcdc_clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct regulator *lcd_supply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u32 pseudo_palette[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct fb_videomode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct lcd_ctrl_config cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static struct fb_var_screeninfo da8xx_fb_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct fb_fix_screeninfo da8xx_fb_fix = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .id = "DA8xx FB Drv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .type = FB_TYPE_PACKED_PIXELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .type_aux = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .visual = FB_VISUAL_PSEUDOCOLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .xpanstep = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .ypanstep = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .ywrapstep = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .accel = FB_ACCEL_NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static struct fb_videomode known_lcd_panels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Sharp LCD035Q3DG01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .name = "Sharp_LCD035Q3DG01",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .xres = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .yres = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .pixclock = KHZ2PICOS(4607),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .left_margin = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .right_margin = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .upper_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .lower_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .hsync_len = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .vsync_len = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .sync = FB_SYNC_CLK_INVERT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Sharp LK043T1DG01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .name = "Sharp_LK043T1DG01",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .xres = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .yres = 272,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .pixclock = KHZ2PICOS(7833),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .left_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .right_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .upper_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .lower_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .hsync_len = 41,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .vsync_len = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .sync = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .flag = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) [2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* Hitachi SP10Q010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .name = "SP10Q010",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .xres = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .yres = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .pixclock = KHZ2PICOS(7833),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .left_margin = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .right_margin = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .upper_margin = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .lower_margin = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .hsync_len = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .vsync_len = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .sync = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .flag = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) [3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Densitron 84-0023-001T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .name = "Densitron_84-0023-001T",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .xres = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .yres = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .pixclock = KHZ2PICOS(6400),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .left_margin = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .right_margin = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .upper_margin = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .lower_margin = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .hsync_len = 30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .vsync_len = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .sync = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static bool da8xx_fb_is_raster_enabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* Enable the Raster Engine of the LCD Controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void lcd_enable_raster(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Put LCDC in reset for several cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (lcd_revision == LCD_VERSION_2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Write 1 to reset LCDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* Bring LCDC out of reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (lcd_revision == LCD_VERSION_2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) lcdc_write(0, LCD_CLK_RESET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Above reset sequence doesnot reset register context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) reg = lcdc_read(LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!(reg & LCD_RASTER_ENABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Disable the Raster Engine of the LCD Controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static void lcd_disable_raster(enum da8xx_frame_complete wait_for_frame_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) reg = lcdc_read(LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (reg & LCD_RASTER_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* return if already disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if ((wait_for_frame_done == DA8XX_FRAME_WAIT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) (lcd_revision == LCD_VERSION_2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) frame_done_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ret = wait_event_interruptible_timeout(frame_done_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) frame_done_flag != 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) msecs_to_jiffies(50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pr_err("LCD Controller timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) u32 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u32 end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u32 reg_ras;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u32 reg_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) u32 reg_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* init reg to clear PLM (loading mode) fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) reg_ras &= ~(3 << 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) reg_dma = lcdc_read(LCD_DMA_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (load_mode == LOAD_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) start = par->dma_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) end = par->dma_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (lcd_revision == LCD_VERSION_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) LCD_V2_END_OF_FRAME0_INT_ENA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) LCD_V2_END_OF_FRAME1_INT_ENA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) LCD_FRAME_DONE | LCD_SYNC_LOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } else if (load_mode == LOAD_PALETTE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) start = par->p_palette_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) end = start + par->palette_sz - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (lcd_revision == LCD_VERSION_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) reg_ras |= LCD_V1_PL_INT_ENA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) LCD_V2_PL_INT_ENA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) lcdc_write(reg_dma, LCD_DMA_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * The Raster enable bit must be set after all other control fields are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) lcd_enable_raster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* Configure the Burst Size and fifo threhold of DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static int lcd_cfg_dma(int burst_size, int fifo_th)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) switch (burst_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) reg |= (fifo_th << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) lcdc_write(reg, LCD_DMA_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static void lcd_cfg_ac_bias(int period, int transitions_per_int)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* Set the AC Bias Period and Number of Transisitons per Interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) reg |= LCD_AC_BIAS_FREQUENCY(period) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int front_porch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) reg |= (((back_porch-1) & 0xff) << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) | (((front_porch-1) & 0xff) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) | (((pulse_width-1) & 0x3f) << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * LCDC Version 2 adds some extra bits that increase the allowable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * size of the horizontal timing registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * remember that the registers use 0 to represent 1 so all values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * that get set into register need to be decremented by 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (lcd_revision == LCD_VERSION_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* Mask off the bits we want to change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & ~0x780000ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) reg |= ((front_porch-1) & 0x300) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) reg |= ((back_porch-1) & 0x300) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) reg |= ((pulse_width-1) & 0x3c0) << 21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int front_porch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) reg |= ((back_porch & 0xff) << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) | ((front_porch & 0xff) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) | (((pulse_width-1) & 0x3f) << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct fb_videomode *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) u32 reg_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) LCD_MONO_8BIT_MODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) LCD_MONOCHROME_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) switch (cfg->panel_shade) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case MONOCHROME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) reg |= LCD_MONOCHROME_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (cfg->mono_8bit_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) reg |= LCD_MONO_8BIT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) case COLOR_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) reg |= LCD_TFT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (cfg->tft_alt_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) reg |= LCD_TFT_ALT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) case COLOR_PASSIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* AC bias applicable only for Pasive panels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (cfg->bpp == 12 && cfg->stn_565_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) reg |= LCD_STN_565_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* enable additional interrupts here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (lcd_revision == LCD_VERSION_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) reg |= LCD_V1_UNDERFLOW_INT_ENA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) LCD_V2_UNDERFLOW_INT_ENA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) lcdc_write(reg, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) reg |= LCD_SYNC_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (cfg->sync_edge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) reg |= LCD_SYNC_EDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) reg &= ~LCD_SYNC_EDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if ((panel->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) reg |= LCD_INVERT_LINE_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) reg &= ~LCD_INVERT_LINE_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if ((panel->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) reg |= LCD_INVERT_FRAME_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) reg &= ~LCD_INVERT_FRAME_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) u32 bpp, u32 raster_order)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (bpp > 16 && lcd_revision == LCD_VERSION_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* Set the Panel Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /* Pixels per line = (PPL + 1)*16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (lcd_revision == LCD_VERSION_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * 0x3F in bits 4..9 gives max horizontal resolution = 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * pixels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) width &= 0x3f0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * 0x7F in bits 4..10 gives max horizontal resolution = 2048
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * pixels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) width &= 0x7f0;
^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) reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) reg &= 0xfffffc00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (lcd_revision == LCD_VERSION_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) reg |= ((width >> 4) - 1) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) width = (width >> 4) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* Set the Panel Height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* Set bits 9:0 of Lines Per Pixel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* Set bit 10 of Lines Per Pixel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (lcd_revision == LCD_VERSION_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) reg |= ((height - 1) & 0x400) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* Set the Raster Order of the Frame Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (raster_order)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) reg |= LCD_RASTER_ORDER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) par->palette_sz = 16 * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) reg |= LCD_V2_TFT_24BPP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) reg |= LCD_V2_TFT_24BPP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) reg |= LCD_V2_TFT_24BPP_UNPACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) par->palette_sz = 256 * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) lcdc_write(reg, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) #define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) unsigned blue, unsigned transp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) unsigned short *palette = (unsigned short *) par->v_palette_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) u_short pal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) int update_hw = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (regno > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) switch (info->fix.visual) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) case FB_VISUAL_TRUECOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) red = CNVT_TOHW(red, info->var.red.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) green = CNVT_TOHW(green, info->var.green.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) blue = CNVT_TOHW(blue, info->var.blue.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) case FB_VISUAL_PSEUDOCOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) switch (info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (regno > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (info->var.grayscale) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) pal = regno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) red >>= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) green >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) blue >>= 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) pal = red & 0x0f00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) pal |= green & 0x00f0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) pal |= blue & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (regno == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) pal |= 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) palette[regno] = pal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) red >>= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) green >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) blue >>= 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) pal = (red & 0x0f00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) pal |= (green & 0x00f0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) pal |= (blue & 0x000f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (palette[regno] != pal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) update_hw = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) palette[regno] = pal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* Truecolor has hardware independent palette */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (regno > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) v = (red << info->var.red.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) (green << info->var.green.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) (blue << info->var.blue.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ((u32 *) (info->pseudo_palette))[regno] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (palette[0] != 0x4000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) update_hw = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) palette[0] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* Update the palette in the h/w as needed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (update_hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) lcd_blit(LOAD_PALETTE, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) #undef CNVT_TOHW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static void da8xx_fb_lcd_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* DMA has to be disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) lcdc_write(0, LCD_DMA_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) lcdc_write(0, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (lcd_revision == LCD_VERSION_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) lcdc_write(0, LCD_INT_ENABLE_SET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /* Write 1 to reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) lcdc_write(0, LCD_CLK_RESET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) unsigned lcdc_clk_div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) unsigned lcdc_clk_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (par->lcdc_clk_rate != lcdc_clk_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ret = clk_set_rate(par->lcdc_clk, lcdc_clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) dev_err(par->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) "unable to set clock rate at %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) lcdc_clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /* Configure the LCD clock divisor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) lcdc_write(LCD_CLK_DIVISOR(lcdc_clk_div) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (lcd_revision == LCD_VERSION_2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) unsigned pixclock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) unsigned *lcdc_clk_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) unsigned lcdc_clk_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) pixclock = PICOS2KHZ(pixclock) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) *lcdc_clk_rate = par->lcdc_clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (pixclock < (*lcdc_clk_rate / CLK_MAX_DIV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) *lcdc_clk_rate = clk_round_rate(par->lcdc_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) pixclock * CLK_MAX_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) lcdc_clk_div = CLK_MAX_DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) } else if (pixclock > (*lcdc_clk_rate / CLK_MIN_DIV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) *lcdc_clk_rate = clk_round_rate(par->lcdc_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) pixclock * CLK_MIN_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) lcdc_clk_div = CLK_MIN_DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) lcdc_clk_div = *lcdc_clk_rate / pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return lcdc_clk_div;
^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 int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct fb_videomode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) unsigned lcdc_clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) unsigned lcdc_clk_div = da8xx_fb_calc_clk_divider(par, mode->pixclock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) &lcdc_clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return da8xx_fb_config_clk_divider(par, lcdc_clk_div, lcdc_clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) unsigned pixclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) unsigned lcdc_clk_div, lcdc_clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) lcdc_clk_div = da8xx_fb_calc_clk_divider(par, pixclock, &lcdc_clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return KHZ2PICOS(lcdc_clk_rate / (1000 * lcdc_clk_div));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct fb_videomode *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) u32 bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ret = da8xx_fb_calc_config_clk_divider(par, panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) dev_err(par->dev, "unable to configure clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (panel->sync & FB_SYNC_CLK_INVERT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* Configure the DMA burst size and fifo threshold. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* Configure the vertical and horizontal sync properties. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) lcd_cfg_vertical_sync(panel->upper_margin, panel->vsync_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) panel->lower_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) lcd_cfg_horizontal_sync(panel->left_margin, panel->hsync_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) panel->right_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* Configure for disply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) ret = lcd_cfg_display(cfg, panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) bpp = cfg->bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (bpp == 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) (unsigned int)panel->yres, bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) cfg->raster_order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /* Configure FDD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) (cfg->fdd << 12), LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /* IRQ handler for version 2 of LCDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct da8xx_fb_par *par = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) lcd_disable_raster(DA8XX_FRAME_NOWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) lcdc_write(stat, LCD_MASKED_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) lcd_enable_raster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) } else if (stat & LCD_PL_LOAD_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * Must disable raster before changing state of any control bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * And also must be disabled before clearing the PL loading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * interrupt via the following write to the status register. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * this is done after then one gets multiple PL done interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) lcd_disable_raster(DA8XX_FRAME_NOWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) lcdc_write(stat, LCD_MASKED_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* Disable PL completion interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /* Setup and start data loading mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) lcd_blit(LOAD_DATA, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) lcdc_write(stat, LCD_MASKED_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (stat & LCD_END_OF_FRAME0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) par->which_dma_channel_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) lcdc_write(par->dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) lcdc_write(par->dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) par->vsync_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) wake_up_interruptible(&par->vsync_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (stat & LCD_END_OF_FRAME1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) par->which_dma_channel_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) lcdc_write(par->dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) lcdc_write(par->dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) par->vsync_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) wake_up_interruptible(&par->vsync_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* Set only when controller is disabled and at the end of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * active frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (stat & BIT(0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) frame_done_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) wake_up_interruptible(&frame_done_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) lcdc_write(0, LCD_END_OF_INT_IND_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* IRQ handler for version 1 LCDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) struct da8xx_fb_par *par = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) u32 stat = lcdc_read(LCD_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) u32 reg_ras;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) lcd_disable_raster(DA8XX_FRAME_NOWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) lcdc_write(stat, LCD_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) lcd_enable_raster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) } else if (stat & LCD_PL_LOAD_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * Must disable raster before changing state of any control bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * And also must be disabled before clearing the PL loading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * interrupt via the following write to the status register. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * this is done after then one gets multiple PL done interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) lcd_disable_raster(DA8XX_FRAME_NOWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) lcdc_write(stat, LCD_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* Disable PL completion inerrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) reg_ras &= ~LCD_V1_PL_INT_ENA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* Setup and start data loading mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) lcd_blit(LOAD_DATA, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) lcdc_write(stat, LCD_STAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (stat & LCD_END_OF_FRAME0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) par->which_dma_channel_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) lcdc_write(par->dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) lcdc_write(par->dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) par->vsync_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) wake_up_interruptible(&par->vsync_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (stat & LCD_END_OF_FRAME1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) par->which_dma_channel_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) lcdc_write(par->dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) lcdc_write(par->dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) par->vsync_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) wake_up_interruptible(&par->vsync_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static int fb_check_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int bpp = var->bits_per_pixel >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) unsigned long line_size = var->xres_virtual * bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) var->red.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) var->green.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) var->transp.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) var->transp.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) var->nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) var->red.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) var->red.length = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) var->green.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) var->green.length = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) var->blue.length = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) var->transp.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) var->transp.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) var->nonstd = FB_NONSTD_REV_PIX_IN_B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) case 16: /* RGB 565 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) var->red.offset = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) var->red.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) var->green.length = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) var->transp.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) var->transp.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) var->nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) var->nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) var->transp.offset = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) var->transp.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) var->nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) var->red.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) var->green.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) var->blue.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) var->transp.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (line_size * var->yres_virtual > par->vram_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) var->yres_virtual = par->vram_size / line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (var->yres > var->yres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) var->yres = var->yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (var->xres > var->xres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) var->xres = var->xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (var->xres + var->xoffset > var->xres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) var->xoffset = var->xres_virtual - var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (var->yres + var->yoffset > var->yres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) var->yoffset = var->yres_virtual - var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) var->pixclock = da8xx_fb_round_clk(par, var->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) unsigned long val, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct da8xx_fb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) par = container_of(nb, struct da8xx_fb_par, freq_transition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (val == CPUFREQ_POSTCHANGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (par->lcdc_clk_rate != clk_get_rate(par->lcdc_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) lcd_disable_raster(DA8XX_FRAME_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) da8xx_fb_calc_config_clk_divider(par, &par->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (par->blank == FB_BLANK_UNBLANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) lcd_enable_raster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) return cpufreq_register_notifier(&par->freq_transition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) CPUFREQ_TRANSITION_NOTIFIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) cpufreq_unregister_notifier(&par->freq_transition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) CPUFREQ_TRANSITION_NOTIFIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) static int fb_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct fb_info *info = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) lcd_da8xx_cpufreq_deregister(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (par->lcd_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret = regulator_disable(par->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) lcd_disable_raster(DA8XX_FRAME_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) lcdc_write(0, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) /* disable DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) lcdc_write(0, LCD_DMA_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) pm_runtime_put_sync(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) pm_runtime_disable(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * Function to wait for vertical sync which for this LCD peripheral
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * translates into waiting for the current raster frame to complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) static int fb_wait_for_vsync(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * Set flag to 0 and wait for isr to set to 1. It would seem there is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * race condition here where the ISR could have occurred just before or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) * just after this set. But since we are just coarsely waiting for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * a frame to complete then that's OK. i.e. if the frame completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * just before this code executed then we have to wait another full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * frame time but there is no way to avoid such a situation. On the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * other hand if the frame completed just after then we don't need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * to wait long at all. Either way we are guaranteed to return to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * user immediately after a frame completion which is all that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) par->vsync_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) ret = wait_event_interruptible_timeout(par->vsync_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) par->vsync_flag != 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) par->vsync_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static int fb_ioctl(struct fb_info *info, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct lcd_sync_arg sync_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) case FBIOGET_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) case FBIOPUT_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) case FBIGET_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) case FBIPUT_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) case FBIGET_COLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) case FBIPUT_COLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) case FBIPUT_HSYNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (copy_from_user(&sync_arg, (char *)arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) sizeof(struct lcd_sync_arg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) lcd_cfg_horizontal_sync(sync_arg.back_porch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) sync_arg.pulse_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) sync_arg.front_porch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) case FBIPUT_VSYNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (copy_from_user(&sync_arg, (char *)arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) sizeof(struct lcd_sync_arg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) lcd_cfg_vertical_sync(sync_arg.back_porch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) sync_arg.pulse_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) sync_arg.front_porch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) case FBIO_WAITFORVSYNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return fb_wait_for_vsync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) static int cfb_blank(int blank, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (par->blank == blank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) par->blank = blank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) switch (blank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) lcd_enable_raster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (par->lcd_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) ret = regulator_enable(par->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (par->lcd_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) ret = regulator_disable(par->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) lcd_disable_raster(DA8XX_FRAME_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * Set new x,y offsets in the virtual display for the visible area and switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) * to the new mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) static int da8xx_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) struct fb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) struct fb_var_screeninfo new_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) struct da8xx_fb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct fb_fix_screeninfo *fix = &fbi->fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) unsigned int end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) unsigned int start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) unsigned long irq_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (var->xoffset != fbi->var.xoffset ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) var->yoffset != fbi->var.yoffset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) memcpy(&new_var, &fbi->var, sizeof(new_var));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) new_var.xoffset = var->xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) new_var.yoffset = var->yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (fb_check_var(&new_var, fbi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) memcpy(&fbi->var, &new_var, sizeof(new_var));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) start = fix->smem_start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) new_var.yoffset * fix->line_length +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) new_var.xoffset * fbi->var.bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) end = start + fbi->var.yres * fix->line_length - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) par->dma_start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) par->dma_end = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) spin_lock_irqsave(&par->lock_for_chan_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) irq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (par->which_dma_channel_done == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) lcdc_write(par->dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) lcdc_write(par->dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) } else if (par->which_dma_channel_done == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) lcdc_write(par->dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) lcdc_write(par->dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) spin_unlock_irqrestore(&par->lock_for_chan_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) irq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) static int da8xxfb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) bool raster = da8xx_fb_is_raster_enabled();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (raster)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) lcd_disable_raster(DA8XX_FRAME_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) fb_var_to_videomode(&par->mode, &info->var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) par->cfg.bpp = info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) info->fix.visual = (par->cfg.bpp <= 8) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) ret = lcd_init(par, &par->cfg, &par->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) dev_err(par->dev, "lcd init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) par->dma_start = info->fix.smem_start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) info->var.yoffset * info->fix.line_length +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) info->var.xoffset * info->var.bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) par->dma_end = par->dma_start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) info->var.yres * info->fix.line_length - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (raster)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) lcd_enable_raster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) static const struct fb_ops da8xx_fb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) .fb_check_var = fb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) .fb_set_par = da8xxfb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) .fb_setcolreg = fb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) .fb_pan_display = da8xx_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) .fb_ioctl = fb_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) .fb_fillrect = cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) .fb_imageblit = cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .fb_blank = cfb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) struct fb_videomode *lcdc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) for (i = 0, lcdc_info = known_lcd_panels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (i == ARRAY_SIZE(known_lcd_panels)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) dev_err(&dev->dev, "no panel found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) dev_info(&dev->dev, "found %s panel\n", lcdc_info->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) return lcdc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) static int fb_probe(struct platform_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) struct da8xx_lcdc_platform_data *fb_pdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) dev_get_platdata(&device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) struct lcd_ctrl_config *lcd_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) struct fb_videomode *lcdc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct fb_info *da8xx_fb_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) struct da8xx_fb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct clk *tmp_lcdc_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) unsigned long ulcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (fb_pdata == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) dev_err(&device->dev, "Can not get platform data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) lcdc_info = da8xx_fb_get_videomode(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (lcdc_info == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (IS_ERR(da8xx_fb_reg_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) return PTR_ERR(da8xx_fb_reg_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) tmp_lcdc_clk = devm_clk_get(&device->dev, "fck");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (IS_ERR(tmp_lcdc_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) dev_err(&device->dev, "Can not get device clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) return PTR_ERR(tmp_lcdc_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) pm_runtime_enable(&device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) pm_runtime_get_sync(&device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) /* Determine LCD IP Version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) switch (lcdc_read(LCD_PID_REG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) case 0x4C100102:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) lcd_revision = LCD_VERSION_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) case 0x4F200800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) case 0x4F201000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) lcd_revision = LCD_VERSION_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) "defaulting to LCD revision 1\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) lcdc_read(LCD_PID_REG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) lcd_revision = LCD_VERSION_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (!lcd_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) goto err_pm_runtime_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) &device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (!da8xx_fb_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) goto err_pm_runtime_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) par = da8xx_fb_info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) par->dev = &device->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) par->lcdc_clk = tmp_lcdc_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (IS_ERR(par->lcd_supply)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (PTR_ERR(par->lcd_supply) == -EPROBE_DEFER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) ret = -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) par->lcd_supply = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) ret = regulator_enable(par->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) par->cfg = *lcd_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) da8xx_fb_lcd_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) /* allocate frame buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) par->vram_size = roundup(par->vram_size/8, ulcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) par->vram_virt = dmam_alloc_coherent(par->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) par->vram_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) &par->vram_phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (!par->vram_virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) dev_err(&device->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) "GLCD: kmalloc for frame buffer failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) da8xx_fb_fix.smem_start = par->vram_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) da8xx_fb_fix.smem_len = par->vram_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) par->dma_start = par->vram_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) par->dma_end = par->dma_start + lcdc_info->yres *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) da8xx_fb_fix.line_length - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) /* allocate palette buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) &par->p_palette_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (!par->v_palette_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) dev_err(&device->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) "GLCD: kmalloc for palette buffer failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) par->irq = platform_get_irq(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (par->irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) da8xx_fb_var.grayscale =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) /* Initialize fbinfo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) da8xx_fb_info->fix = da8xx_fb_fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) da8xx_fb_info->var = da8xx_fb_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) da8xx_fb_info->fbops = &da8xx_fb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) da8xx_fb_info->pseudo_palette = par->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) da8xx_fb_info->cmap.len = par->palette_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) /* initialize var_screeninfo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) fb_set_var(da8xx_fb_info, &da8xx_fb_var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) dev_set_drvdata(&device->dev, da8xx_fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) /* initialize the vsync wait queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) init_waitqueue_head(&par->vsync_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) par->vsync_timeout = HZ / 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) par->which_dma_channel_done = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) spin_lock_init(&par->lock_for_chan_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) /* Register the Frame Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (register_framebuffer(da8xx_fb_info) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) dev_err(&device->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) "GLCD: Frame Buffer Registration Failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) goto err_dealloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) ret = lcd_da8xx_cpufreq_register(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) dev_err(&device->dev, "failed to register cpufreq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) goto err_cpu_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (lcd_revision == LCD_VERSION_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) lcdc_irq_handler = lcdc_irq_handler_rev01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) init_waitqueue_head(&frame_done_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) lcdc_irq_handler = lcdc_irq_handler_rev02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) DRIVER_NAME, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) goto irq_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) irq_freq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) lcd_da8xx_cpufreq_deregister(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) err_cpu_freq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) unregister_framebuffer(da8xx_fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) err_dealloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) fb_dealloc_cmap(&da8xx_fb_info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) err_release_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) framebuffer_release(da8xx_fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) err_pm_runtime_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) pm_runtime_put_sync(&device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) pm_runtime_disable(&device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) static struct lcdc_context {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) u32 clk_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) u32 ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) u32 dma_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) u32 raster_timing_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) u32 raster_timing_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) u32 raster_timing_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) u32 int_enable_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) u32 dma_frm_buf_base_addr_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) u32 dma_frm_buf_ceiling_addr_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) u32 dma_frm_buf_base_addr_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) u32 dma_frm_buf_ceiling_addr_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) u32 raster_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) } reg_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) static void lcd_context_save(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if (lcd_revision == LCD_VERSION_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) reg_context.ctrl = lcdc_read(LCD_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) reg_context.dma_frm_buf_base_addr_0 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) reg_context.dma_frm_buf_ceiling_addr_0 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) reg_context.dma_frm_buf_base_addr_1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) reg_context.dma_frm_buf_ceiling_addr_1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) static void lcd_context_restore(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (lcd_revision == LCD_VERSION_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) lcdc_write(reg_context.ctrl, LCD_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) lcdc_write(reg_context.dma_frm_buf_base_addr_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) lcdc_write(reg_context.dma_frm_buf_base_addr_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) static int fb_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (par->lcd_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) ret = regulator_disable(par->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) fb_set_suspend(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) lcd_disable_raster(DA8XX_FRAME_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) lcd_context_save();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) pm_runtime_put_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) static int fb_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) struct da8xx_fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) lcd_context_restore();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (par->blank == FB_BLANK_UNBLANK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) lcd_enable_raster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) if (par->lcd_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) ret = regulator_enable(par->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) fb_set_suspend(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) static SIMPLE_DEV_PM_OPS(fb_pm_ops, fb_suspend, fb_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) static struct platform_driver da8xx_fb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) .probe = fb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) .remove = fb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) .pm = &fb_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) module_platform_driver(da8xx_fb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) MODULE_AUTHOR("Texas Instruments");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) MODULE_LICENSE("GPL");