^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/pxafb.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 1999 Eric A. Thomas.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004 Jean-Frederic Clere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2004 Ian Campbell.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2004 Jeff Lackey.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Based on sa1100fb.c Copyright (C) 1999 Eric A. Thomas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * which in turn is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Based on acornfb.c Copyright (C) Russell King.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Intel PXA250/210 LCD Controller Frame Buffer Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Please direct your questions and comments on this driver to the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * email address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * linux-arm-kernel@lists.arm.linux.org.uk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Add support for overlay1 and overlay2 based on pxafb_overlay.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Copyright (C) 2004, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 2003/08/27: <yu.tang@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * 2004/03/10: <stanley.cai@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 2004/10/28: <yan.yin@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Copyright (C) 2006-2008 Marvell International Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * All Rights Reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/freezer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <video/of_display_timing.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <video/videomode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #include <mach/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <linux/platform_data/video-pxafb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Complain if VAR is out of range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define DEBUG_VAR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include "pxafb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Bits which should not be set in machine configuration structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define LCCR0_INVALID_CONFIG_MASK (LCCR0_OUM | LCCR0_BM | LCCR0_QDM |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) LCCR0_DIS | LCCR0_EFM | LCCR0_IUM |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) LCCR0_SFM | LCCR0_LDM | LCCR0_ENB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP | LCCR3_VSP |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) LCCR3_PCD | LCCR3_BPP(0xf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int pxafb_activate_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct pxafb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void setup_base_frame(struct pxafb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct fb_var_screeninfo *var, int branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned long offset, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static unsigned long video_mem_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static inline unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) lcd_readl(struct pxafb_info *fbi, unsigned int off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return __raw_readl(fbi->mmio_base + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) lcd_writel(struct pxafb_info *fbi, unsigned int off, unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) __raw_writel(val, fbi->mmio_base + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * We need to handle two requests being made at the same time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * There are two important cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * 1. When we are changing VT (C_REENABLE) while unblanking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * (C_ENABLE) We must perform the unblanking, which will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * do our REENABLE for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * 2. When we are blanking, but immediately unblank before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * we have blanked. We do the "REENABLE" thing here as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * well, just to be sure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (fbi->task_state == C_ENABLE && state == C_REENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) state = (u_int) -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (fbi->task_state == C_DISABLE && state == C_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) state = C_REENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (state != (u_int)-1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) fbi->task_state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) schedule_work(&fbi->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) chan &= 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) chan >>= 16 - bf->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return chan << bf->offset;
^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) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u_int trans, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u_int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (regno >= fbi->palette_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (fbi->fb.var.grayscale) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) fbi->palette_cpu[regno] = ((blue >> 8) & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) switch (fbi->lccr4 & LCCR4_PAL_FOR_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) case LCCR4_PAL_FOR_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) val = ((red >> 0) & 0xf800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) val |= ((green >> 5) & 0x07e0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) val |= ((blue >> 11) & 0x001f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) fbi->palette_cpu[regno] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case LCCR4_PAL_FOR_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) val = ((red << 8) & 0x00f80000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) val |= ((green >> 0) & 0x0000fc00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) val |= ((blue >> 8) & 0x000000f8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ((u32 *)(fbi->palette_cpu))[regno] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case LCCR4_PAL_FOR_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) val = ((red << 8) & 0x00fc0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) val |= ((green >> 0) & 0x0000fc00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) val |= ((blue >> 8) & 0x000000fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ((u32 *)(fbi->palette_cpu))[regno] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case LCCR4_PAL_FOR_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) val = ((red << 8) & 0x00ff0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) val |= ((green >> 0) & 0x0000ff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) val |= ((blue >> 8) & 0x000000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ((u32 *)(fbi->palette_cpu))[regno] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u_int trans, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * If inverse mode was selected, invert all the colours
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * rather than the register number. The register number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * is what you poke into the framebuffer to produce the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * colour you requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (fbi->cmap_inverse) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) red = 0xffff - red;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) green = 0xffff - green;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) blue = 0xffff - blue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * If greyscale is true, then we convert the RGB value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * to greyscale no matter what visual we are using.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (fbi->fb.var.grayscale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) red = green = blue = (19595 * red + 38470 * green +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 7471 * blue) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) switch (fbi->fb.fix.visual) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case FB_VISUAL_TRUECOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * 16-bit True Colour. We encode the RGB value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * according to the RGB bitfield information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (regno < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u32 *pal = fbi->fb.pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) val = chan_to_field(red, &fbi->fb.var.red);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) val |= chan_to_field(green, &fbi->fb.var.green);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) val |= chan_to_field(blue, &fbi->fb.var.blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) pal[regno] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) case FB_VISUAL_STATIC_PSEUDOCOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case FB_VISUAL_PSEUDOCOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* calculate pixel depth, transparency bit included, >=16bpp formats _only_ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static inline int var_to_depth(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return var->red.length + var->green.length +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) var->blue.length + var->transp.length;
^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) /* calculate 4-bit BPP value for LCCR3 and OVLxC1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int pxafb_var_to_bpp(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int bpp = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case 1: bpp = 0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case 2: bpp = 1; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case 4: bpp = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case 8: bpp = 3; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case 16: bpp = 4; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) switch (var_to_depth(var)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case 18: bpp = 6; break; /* 18-bits/pixel packed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case 19: bpp = 8; break; /* 19-bits/pixel packed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case 24: bpp = 9; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) switch (var_to_depth(var)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case 18: bpp = 5; break; /* 18-bits/pixel unpacked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case 19: bpp = 7; break; /* 19-bits/pixel unpacked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case 25: bpp = 10; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * pxafb_var_to_lccr3():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * Convert a bits per pixel value to the correct bit pattern for LCCR3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * NOTE: for PXA27x with overlays support, the LCCR3_PDFOR_x bits have an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * implication of the acutal use of transparency bit, which we handle it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * here separatedly. See PXA27x Developer's Manual, Section <<7.4.6 Pixel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * Formats>> for the valid combination of PDFOR, PAL_FOR for various BPP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * Transparency for palette pixel formats is not supported at the moment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static uint32_t pxafb_var_to_lccr3(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int bpp = pxafb_var_to_bpp(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) uint32_t lccr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (bpp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) lccr3 = LCCR3_BPP(bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) switch (var_to_depth(var)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case 16: lccr3 |= var->transp.length ? LCCR3_PDFOR_3 : 0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case 18: lccr3 |= LCCR3_PDFOR_3; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case 24: lccr3 |= var->transp.length ? LCCR3_PDFOR_2 : LCCR3_PDFOR_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case 19:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case 25: lccr3 |= LCCR3_PDFOR_0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return lccr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) #define SET_PIXFMT(v, r, g, b, t) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) (v)->transp.offset = (t) ? (r) + (g) + (b) : 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) (v)->transp.length = (t) ? (t) : 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) (v)->blue.length = (b); (v)->blue.offset = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) (v)->green.length = (g); (v)->green.offset = (b); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) (v)->red.length = (r); (v)->red.offset = (b) + (g); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* set the RGBT bitfields of fb_var_screeninf according to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * var->bits_per_pixel and given depth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static void pxafb_set_pixfmt(struct fb_var_screeninfo *var, int depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (depth == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) depth = var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (var->bits_per_pixel < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* indexed pixel formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) var->red.offset = 0; var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) var->green.offset = 0; var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) var->blue.offset = 0; var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) var->transp.offset = 0; var->transp.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) switch (depth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case 16: var->transp.length ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) SET_PIXFMT(var, 5, 5, 5, 1) : /* RGBT555 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) SET_PIXFMT(var, 5, 6, 5, 0); break; /* RGB565 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) case 18: SET_PIXFMT(var, 6, 6, 6, 0); break; /* RGB666 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) case 19: SET_PIXFMT(var, 6, 6, 6, 1); break; /* RGBT666 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case 24: var->transp.length ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) SET_PIXFMT(var, 8, 8, 7, 1) : /* RGBT887 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) SET_PIXFMT(var, 8, 8, 8, 0); break; /* RGB888 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case 25: SET_PIXFMT(var, 8, 8, 8, 1); break; /* RGBT888 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^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) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * pxafb_display_dma_period()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * Calculate the minimum period (in picoseconds) between two DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * requests for the LCD controller. If we hit this, it means we're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * doing nothing but LCD DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * Period = pixclock * bits_per_byte * bytes_per_transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * / memory_bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return var->pixclock * 8 * 16 / var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * Select the smallest mode that allows the desired resolution to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * displayed. If desired parameters can be rounded up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct pxafb_mode_info *mode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct pxafb_mode_info *modelist = mach->modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) for (i = 0; i < mach->num_modes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (modelist[i].xres >= var->xres &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) modelist[i].yres >= var->yres &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) modelist[i].xres < best_x &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) modelist[i].yres < best_y &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) modelist[i].bpp >= var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) best_x = modelist[i].xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) best_y = modelist[i].yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) mode = &modelist[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static void pxafb_setmode(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct pxafb_mode_info *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) var->xres = mode->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) var->yres = mode->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) var->bits_per_pixel = mode->bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) var->pixclock = mode->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) var->hsync_len = mode->hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) var->left_margin = mode->left_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) var->right_margin = mode->right_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) var->vsync_len = mode->vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) var->upper_margin = mode->upper_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) var->lower_margin = mode->lower_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) var->sync = mode->sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) var->grayscale = mode->cmap_greyscale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) var->transp.length = mode->transparency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* set the initial RGBA bitfields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) pxafb_set_pixfmt(var, mode->depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int pxafb_adjust_timing(struct pxafb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) var->xres = max_t(int, var->xres, MIN_XRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) var->yres = max_t(int, var->yres, MIN_YRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!(fbi->lccr0 & LCCR0_LCDT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) clamp_val(var->hsync_len, 1, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) clamp_val(var->vsync_len, 1, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) clamp_val(var->left_margin, 1, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) clamp_val(var->right_margin, 1, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) clamp_val(var->upper_margin, 1, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) clamp_val(var->lower_margin, 1, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* make sure each line is aligned on word boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) line_length = var->xres * var->bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) line_length = ALIGN(line_length, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) var->xres = line_length * 8 / var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* we don't support xpan, force xres_virtual to be equal to xres */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (var->accel_flags & FB_ACCELF_TEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) var->yres_virtual = fbi->fb.fix.smem_len / line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) var->yres_virtual = max(var->yres_virtual, var->yres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /* check for limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (var->xres > MAX_XRES || var->yres > MAX_YRES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (var->yres > var->yres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * pxafb_check_var():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Get the video params out of 'var'. If a value doesn't fit, round it up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * if it's too big, return -EINVAL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * Round up in the following order: bits_per_pixel, xres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * bitfields, horizontal timing, vertical timing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct pxafb_mach_info *inf = fbi->inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (inf->fixed_modes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct pxafb_mode_info *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) mode = pxafb_getmode(inf, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) pxafb_setmode(var, mode);
^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) /* do a test conversion to BPP fields to check the color formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) err = pxafb_var_to_bpp(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pxafb_set_pixfmt(var, var_to_depth(var));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) err = pxafb_adjust_timing(fbi, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) pr_debug("pxafb: dma period = %d ps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) pxafb_display_dma_period(var));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * pxafb_set_par():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * Set the user defined part of the display for the specified console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static int pxafb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct fb_var_screeninfo *var = &info->var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (var->bits_per_pixel >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) else if (!fbi->cmap_static)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * Some people have weird ideas about wanting static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * pseudocolor maps. I suspect their user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * applications are broken.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) fbi->fb.fix.line_length = var->xres_virtual *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) var->bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (var->bits_per_pixel >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) fbi->palette_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) fbi->palette_size = var->bits_per_pixel == 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 4 : 1 << var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) fbi->palette_cpu = (u16 *)&fbi->dma_buff->palette[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (fbi->fb.var.bits_per_pixel >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) fb_dealloc_cmap(&fbi->fb.cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) pxafb_activate_var(var, fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static int pxafb_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct fb_var_screeninfo newvar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) int dma = DMA_MAX + DMA_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (fbi->state != C_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* Only take .xoffset, .yoffset and .vmode & FB_VMODE_YWRAP from what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * was passed in and copy the rest from the old screeninfo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) memcpy(&newvar, &fbi->fb.var, sizeof(newvar));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) newvar.xoffset = var->xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) newvar.yoffset = var->yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) newvar.vmode &= ~FB_VMODE_YWRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) newvar.vmode |= var->vmode & FB_VMODE_YWRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) setup_base_frame(fbi, &newvar, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (fbi->lccr0 & LCCR0_SDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) lcd_writel(fbi, FBR0, fbi->fdadr[dma] | 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * pxafb_blank():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * Blank the display by setting all palette values to zero. Note, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * 16 bpp mode does not really use the palette, so this will not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * blank the display in all modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static int pxafb_blank(int blank, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) switch (blank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) for (i = 0; i < fbi->palette_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) pxafb_setpalettereg(i, 0, 0, 0, 0, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) pxafb_schedule_work(fbi, C_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) fb_set_cmap(&fbi->fb.cmap, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) pxafb_schedule_work(fbi, C_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static const struct fb_ops pxafb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) .fb_check_var = pxafb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) .fb_set_par = pxafb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) .fb_pan_display = pxafb_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) .fb_setcolreg = pxafb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) .fb_fillrect = cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) .fb_imageblit = cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) .fb_blank = pxafb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) #ifdef CONFIG_FB_PXA_OVERLAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) static void overlay1fb_setup(struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) int size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) unsigned long start = ofb->video_mem_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) setup_frame_dma(ofb->fbi, DMA_OV1, PAL_NONE, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* Depending on the enable status of overlay1/2, the DMA should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * updated from FDADRx (when disabled) or FBRx (when enabled).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static void overlay1fb_enable(struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int enabled = lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) uint32_t fdadr1 = ofb->fbi->fdadr[DMA_OV1] | (enabled ? 0x1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) lcd_writel(ofb->fbi, enabled ? FBR1 : FDADR1, fdadr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) lcd_writel(ofb->fbi, OVL1C2, ofb->control[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] | OVLxC1_OEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static void overlay1fb_disable(struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) uint32_t lccr5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (!(lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) lccr5 = lcd_readl(ofb->fbi, LCCR5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) pr_warn("%s: timeout disabling overlay1\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) lcd_writel(ofb->fbi, LCCR5, lccr5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static void overlay2fb_setup(struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) int size, div = 1, pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) unsigned long start[3] = { ofb->video_mem_phys, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) size = ofb->fb.var.xres_virtual * ofb->fb.var.yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) switch (pfor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) case OVERLAY_FORMAT_YUV444_PLANAR: div = 1; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) case OVERLAY_FORMAT_YUV422_PLANAR: div = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) case OVERLAY_FORMAT_YUV420_PLANAR: div = 4; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) start[1] = start[0] + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) start[2] = start[1] + size / div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) setup_frame_dma(ofb->fbi, DMA_OV2_Cb, -1, start[1], size / div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) setup_frame_dma(ofb->fbi, DMA_OV2_Cr, -1, start[2], size / div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static void overlay2fb_enable(struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) int pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int enabled = lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) uint32_t fdadr2 = ofb->fbi->fdadr[DMA_OV2_Y] | (enabled ? 0x1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) uint32_t fdadr3 = ofb->fbi->fdadr[DMA_OV2_Cb] | (enabled ? 0x1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) uint32_t fdadr4 = ofb->fbi->fdadr[DMA_OV2_Cr] | (enabled ? 0x1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) lcd_writel(ofb->fbi, enabled ? FBR3 : FDADR3, fdadr3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) lcd_writel(ofb->fbi, enabled ? FBR4 : FDADR4, fdadr4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) lcd_writel(ofb->fbi, OVL2C2, ofb->control[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] | OVLxC1_OEN);
^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 void overlay2fb_disable(struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) uint32_t lccr5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (!(lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) lccr5 = lcd_readl(ofb->fbi, LCCR5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) lcd_writel(ofb->fbi, FBR2, ofb->fbi->fdadr[DMA_OV2_Y] | 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) lcd_writel(ofb->fbi, FBR3, ofb->fbi->fdadr[DMA_OV2_Cb] | 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) pr_warn("%s: timeout disabling overlay2\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static struct pxafb_layer_ops ofb_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .enable = overlay1fb_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .disable = overlay1fb_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .setup = overlay1fb_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) .enable = overlay2fb_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) .disable = overlay2fb_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) .setup = overlay2fb_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static int overlayfb_open(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct pxafb_layer *ofb = container_of(info, struct pxafb_layer, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* no support for framebuffer console on overlay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (user == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (ofb->usage++ == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* unblank the base framebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static int overlayfb_release(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct pxafb_layer *ofb = container_of(info, struct pxafb_layer, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (ofb->usage == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ofb->ops->disable(ofb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ofb->fb.var.height = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) ofb->fb.var.width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) ofb->fb.var.xres = ofb->fb.var.xres_virtual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) ofb->fb.var.yres = ofb->fb.var.yres_virtual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ofb->usage--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static int overlayfb_check_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) struct pxafb_layer *ofb = container_of(info, struct pxafb_layer, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct fb_var_screeninfo *base_var = &ofb->fbi->fb.var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) int xpos, ypos, pfor, bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) xpos = NONSTD_TO_XPOS(var->nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) ypos = NONSTD_TO_YPOS(var->nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) pfor = NONSTD_TO_PFOR(var->nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) bpp = pxafb_var_to_bpp(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (bpp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* no support for YUV format on overlay1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (ofb->id == OVERLAY1 && pfor != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* for YUV packed formats, bpp = 'minimum bpp of YUV components' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) switch (pfor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) case OVERLAY_FORMAT_RGB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) bpp = pxafb_var_to_bpp(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (bpp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) pxafb_set_pixfmt(var, var_to_depth(var));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 8; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 4; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /* each line must start at a 32-bit word boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if ((xpos * bpp) % 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /* xres must align on 32-bit word boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) var->xres = roundup(var->xres * bpp, 32) / bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if ((xpos + var->xres > base_var->xres) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) (ypos + var->yres > base_var->yres))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) var->yres_virtual = max(var->yres, var->yres_virtual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static int overlayfb_check_video_memory(struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) struct fb_var_screeninfo *var = &ofb->fb.var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) int pfor = NONSTD_TO_PFOR(var->nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) int size, bpp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) switch (pfor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) case OVERLAY_FORMAT_RGB: bpp = var->bits_per_pixel; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 24; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 16; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 12; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ofb->fb.fix.line_length = var->xres_virtual * bpp / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ofb->video_mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (ofb->video_mem_size >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static int overlayfb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct pxafb_layer *ofb = container_of(info, struct pxafb_layer, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct fb_var_screeninfo *var = &info->var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int xpos, ypos, pfor, bpp, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) ret = overlayfb_check_video_memory(ofb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) bpp = pxafb_var_to_bpp(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) xpos = NONSTD_TO_XPOS(var->nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) ypos = NONSTD_TO_YPOS(var->nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) pfor = NONSTD_TO_PFOR(var->nonstd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) OVLxC1_BPP(bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ofb->control[1] = OVLxC2_XPOS(xpos) | OVLxC2_YPOS(ypos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (ofb->id == OVERLAY2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) ofb->control[1] |= OVL2C2_PFOR(pfor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ofb->ops->setup(ofb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ofb->ops->enable(ofb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static const struct fb_ops overlay_fb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .fb_open = overlayfb_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .fb_release = overlayfb_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .fb_check_var = overlayfb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .fb_set_par = overlayfb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static void init_pxafb_overlay(struct pxafb_info *fbi, struct pxafb_layer *ofb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) sprintf(ofb->fb.fix.id, "overlay%d", id + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) ofb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) ofb->fb.fix.xpanstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) ofb->fb.fix.ypanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) ofb->fb.var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ofb->fb.var.height = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ofb->fb.var.width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) ofb->fb.var.vmode = FB_VMODE_NONINTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) ofb->fb.fbops = &overlay_fb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) ofb->fb.flags = FBINFO_FLAG_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ofb->fb.node = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) ofb->fb.pseudo_palette = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ofb->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ofb->ops = &ofb_ops[id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) ofb->usage = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) ofb->fbi = fbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) init_completion(&ofb->branch_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static inline int pxafb_overlay_supported(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (cpu_is_pxa27x() || cpu_is_pxa3xx())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static int pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct pxafb_layer *ofb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /* We assume that user will use at most video_mem_size for overlay fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * anyway, it's useless to use 16bpp main plane and 24bpp overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ofb->video_mem = alloc_pages_exact(PAGE_ALIGN(pxafb->video_mem_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) GFP_KERNEL | __GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (ofb->video_mem == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) ofb->video_mem_size = PAGE_ALIGN(pxafb->video_mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) mutex_lock(&ofb->fb.mm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ofb->fb.fix.smem_start = ofb->video_mem_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ofb->fb.fix.smem_len = pxafb->video_mem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) mutex_unlock(&ofb->fb.mm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ofb->fb.screen_base = ofb->video_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return 0;
^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) static void pxafb_overlay_init(struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (!pxafb_overlay_supported())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct pxafb_layer *ofb = &fbi->overlay[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) init_pxafb_overlay(fbi, ofb, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ret = register_framebuffer(&ofb->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) dev_err(fbi->dev, "failed to register overlay %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ret = pxafb_overlay_map_video_memory(fbi, ofb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dev_err(fbi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) "failed to map video memory for overlay %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) unregister_framebuffer(&ofb->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) ofb->registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /* mask all IU/BS/EOF/SOF interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) lcd_writel(fbi, LCCR5, ~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) pr_info("PXA Overlay driver loaded successfully!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) static void pxafb_overlay_exit(struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (!pxafb_overlay_supported())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) struct pxafb_layer *ofb = &fbi->overlay[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (ofb->registered) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (ofb->video_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) free_pages_exact(ofb->video_mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ofb->video_mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) unregister_framebuffer(&ofb->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static inline void pxafb_overlay_init(struct pxafb_info *fbi) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static inline void pxafb_overlay_exit(struct pxafb_info *fbi) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) #endif /* CONFIG_FB_PXA_OVERLAY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * Calculate the PCD value from the clock rate (in picoseconds).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * We take account of the PPCR clock setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) * From PXA Developer's Manual:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * PixelClock = LCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * -------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * 2 ( PCD + 1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * PCD = LCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * ------------- - 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * 2(PixelClock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * Where:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * LCLK = LCD/Memory Clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * PCD = LCCR3[7:0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * PixelClock here is in Hz while the pixclock argument given is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * period in picoseconds. Hence PixelClock = 1 / ( pixclock * 10^-12 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * The function get_lclk_frequency_10khz returns LCLK in units of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * 10khz. Calling the result of this function lclk gives us the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * -------------------------------------- - 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static inline unsigned int get_pcd(struct pxafb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) unsigned int pixclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) unsigned long long pcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /* FIXME: Need to take into account Double Pixel Clock mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * (DPC) bit? or perhaps set it based on the various clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) pcd *= pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) do_div(pcd, 100000000 * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /* no need for this, since we should subtract 1 anyway. they cancel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* pcd += 1; */ /* make up for integer math truncations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return (unsigned int)pcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) * Some touchscreens need hsync information from the video driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * function correctly. We export it here. Note that 'hsync_time' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * the value returned from pxafb_get_hsync_time() is the *reciprocal*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) * of the hsync period in seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) unsigned long htime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) fbi->hsync_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return;
^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) htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) fbi->hsync_time = htime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) unsigned long pxafb_get_hsync_time(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) struct pxafb_info *fbi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* If display is blanked/suspended, hsync isn't active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (!fbi || (fbi->state != C_ENABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return fbi->hsync_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) EXPORT_SYMBOL(pxafb_get_hsync_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) unsigned long start, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct pxafb_dma_descriptor *dma_desc, *pal_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) unsigned int dma_desc_off, pal_desc_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (dma < 0 || dma >= DMA_MAX * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) dma_desc = &fbi->dma_buff->dma_desc[dma];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) dma_desc->fsadr = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) dma_desc->fidr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) dma_desc->ldcmd = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (pal < 0 || pal >= PAL_MAX * 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) pal_desc = &fbi->dma_buff->pal_desc[pal];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) pal_desc_off = offsetof(struct pxafb_dma_buff, pal_desc[pal]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) pal_desc->fidr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) pal_desc->ldcmd = fbi->palette_size * sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) pal_desc->ldcmd = fbi->palette_size * sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) pal_desc->ldcmd |= LDCMD_PAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) /* flip back and forth between palette and frame buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) pal_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) dma_desc->fdadr = fbi->dma_buff_phys + pal_desc_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static void setup_base_frame(struct pxafb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) int branch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) struct fb_fix_screeninfo *fix = &fbi->fb.fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) int nbytes, dma, pal, bpp = var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) dma = DMA_BASE + (branch ? DMA_MAX : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) pal = (bpp >= 16) ? PAL_NONE : PAL_BASE + (branch ? PAL_MAX : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) nbytes = fix->line_length * var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) offset = fix->line_length * var->yoffset + fbi->video_mem_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (fbi->lccr0 & LCCR0_SDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) nbytes = nbytes / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) setup_frame_dma(fbi, dma + 1, PAL_NONE, offset + nbytes, nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) setup_frame_dma(fbi, dma, pal, offset, nbytes);
^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) #ifdef CONFIG_FB_PXA_SMARTPANEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static int setup_smart_dma(struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct pxafb_dma_descriptor *dma_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) unsigned long dma_desc_off, cmd_buff_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) dma_desc = &fbi->dma_buff->dma_desc[DMA_CMD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[DMA_CMD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) cmd_buff_off = offsetof(struct pxafb_dma_buff, cmd_buff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) dma_desc->fsadr = fbi->dma_buff_phys + cmd_buff_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) dma_desc->fidr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) dma_desc->ldcmd = fbi->n_smart_cmds * sizeof(uint16_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) fbi->fdadr[DMA_CMD] = dma_desc->fdadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) int pxafb_smart_flush(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) uint32_t prsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) /* disable controller until all registers are set up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) /* 1. make it an even number of commands to align on 32-bit boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) * 2. add the interrupt command to the end of the chain so we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * keep track of the end of the transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) while (fbi->n_smart_cmds & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_NOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_INTERRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_WAIT_FOR_VSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) setup_smart_dma(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) /* continue to execute next command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) prsr = lcd_readl(fbi, PRSR) | PRSR_ST_OK | PRSR_CON_NT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) lcd_writel(fbi, PRSR, prsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* stop the processor in case it executed "wait for sync" cmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) lcd_writel(fbi, CMDCR, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* don't send interrupts for fifo underruns on channel 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) lcd_writel(fbi, LCCR5, LCCR5_IUM(6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) lcd_writel(fbi, LCCR4, fbi->reg_lccr4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) lcd_writel(fbi, FDADR6, fbi->fdadr[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* begin sending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (wait_for_completion_timeout(&fbi->command_done, HZ/2) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) pr_warn("%s: timeout waiting for command done\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) /* quick disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) prsr = lcd_readl(fbi, PRSR) & ~(PRSR_ST_OK | PRSR_CON_NT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) lcd_writel(fbi, PRSR, prsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) lcd_writel(fbi, FDADR6, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) fbi->n_smart_cmds = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) for (i = 0; i < n_cmds; i++, cmds++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) /* if it is a software delay, flush and delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if ((*cmds & 0xff00) == SMART_CMD_DELAY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) pxafb_smart_flush(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) mdelay(*cmds & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /* leave 2 commands for INTERRUPT and WAIT_FOR_SYNC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (fbi->n_smart_cmds == CMD_BUFF_SIZE - 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) pxafb_smart_flush(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) fbi->smart_cmds[fbi->n_smart_cmds++] = *cmds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) unsigned int t = (time_ns * (lcd_clk / 1000000) / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return (t == 0) ? 1 : t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) static void setup_smart_timing(struct pxafb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct pxafb_mach_info *inf = fbi->inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) struct pxafb_mode_info *mode = &inf->modes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) unsigned long lclk = clk_get_rate(fbi->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) unsigned t1, t2, t3, t4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) t1 = max(mode->a0csrd_set_hld, mode->a0cswr_set_hld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) t2 = max(mode->rd_pulse_width, mode->wr_pulse_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) t3 = mode->op_hold_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) t4 = mode->cmd_inh_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) fbi->reg_lccr1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) LCCR1_DisWdth(var->xres) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) LCCR1_BegLnDel(__smart_timing(t1, lclk)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) LCCR1_EndLnDel(__smart_timing(t2, lclk)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) LCCR1_HorSnchWdth(__smart_timing(t3, lclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) fbi->reg_lccr2 = LCCR2_DisHght(var->yres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) fbi->reg_lccr3 = fbi->lccr3 | LCCR3_PixClkDiv(__smart_timing(t4, lclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) fbi->reg_lccr3 |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HSP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) fbi->reg_lccr3 |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VSP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /* FIXME: make this configurable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) fbi->reg_cmdcr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) static int pxafb_smart_thread(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) struct pxafb_info *fbi = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct pxafb_mach_info *inf = fbi->inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (!inf->smart_update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) pr_err("%s: not properly initialized, thread terminated\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) pr_debug("%s(): task starting\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) set_freezable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) while (!kthread_should_stop()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (try_to_freeze())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) mutex_lock(&fbi->ctrlr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (fbi->state == C_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) inf->smart_update(&fbi->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) complete(&fbi->refresh_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) mutex_unlock(&fbi->ctrlr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) schedule_timeout(msecs_to_jiffies(30));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) pr_debug("%s(): task ending\n", __func__);
^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 int pxafb_smart_init(struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (!(fbi->lccr0 & LCCR0_LCDT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) fbi->n_smart_cmds = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) init_completion(&fbi->command_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) init_completion(&fbi->refresh_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) "lcd_refresh");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (IS_ERR(fbi->smart_thread)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) pr_err("%s: unable to create kernel thread\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return PTR_ERR(fbi->smart_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) #endif /* CONFIG_FB_PXA_SMARTPANEL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) static void setup_parallel_timing(struct pxafb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) fbi->reg_lccr1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) LCCR1_DisWdth(var->xres) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) LCCR1_HorSnchWdth(var->hsync_len) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) LCCR1_BegLnDel(var->left_margin) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) LCCR1_EndLnDel(var->right_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * If we have a dual scan LCD, we need to halve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * the YRES parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) lines_per_panel = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) lines_per_panel /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) fbi->reg_lccr2 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) LCCR2_DisHght(lines_per_panel) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) LCCR2_VrtSnchWdth(var->vsync_len) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) LCCR2_BegFrmDel(var->upper_margin) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) LCCR2_EndFrmDel(var->lower_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) fbi->reg_lccr3 = fbi->lccr3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) (var->sync & FB_SYNC_HOR_HIGH_ACT ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) LCCR3_HorSnchH : LCCR3_HorSnchL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) (var->sync & FB_SYNC_VERT_HIGH_ACT ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) LCCR3_VrtSnchH : LCCR3_VrtSnchL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (pcd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) fbi->reg_lccr3 |= LCCR3_PixClkDiv(pcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) set_hsync_time(fbi, pcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * pxafb_activate_var():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * Configures LCD Controller based on entries in var parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * Settings are only written to the controller if changes were made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) static int pxafb_activate_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) u_long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) /* Update shadow copy atomically */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) #ifdef CONFIG_FB_PXA_SMARTPANEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (fbi->lccr0 & LCCR0_LCDT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) setup_smart_timing(fbi, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) setup_parallel_timing(fbi, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) setup_base_frame(fbi, var, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) fbi->reg_lccr0 = fbi->lccr0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) LCCR0_QDM | LCCR0_BM | LCCR0_OUM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) fbi->reg_lccr3 |= pxafb_var_to_lccr3(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * Only update the registers if the controller is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * and something has changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if ((lcd_readl(fbi, LCCR0) != fbi->reg_lccr0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) (lcd_readl(fbi, LCCR1) != fbi->reg_lccr1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) (lcd_readl(fbi, LCCR2) != fbi->reg_lccr2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) ((fbi->lccr0 & LCCR0_SDS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) pxafb_schedule_work(fbi, C_REENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^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) * NOTE! The following functions are purely helpers for set_ctrlr_state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) * Do not call them directly; set_ctrlr_state does the correct serialisation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) * to ensure that things happen in the right way 100% of time time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) * -- rmk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (fbi->backlight_power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) fbi->backlight_power(on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (fbi->lcd_power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) fbi->lcd_power(on, &fbi->fb.var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (fbi->lcd_supply && fbi->lcd_supply_enabled != on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) ret = regulator_enable(fbi->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) ret = regulator_disable(fbi->lcd_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) pr_warn("Unable to %s LCD supply regulator: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) on ? "enable" : "disable", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) fbi->lcd_supply_enabled = on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) static void pxafb_enable_controller(struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) pr_debug("pxafb: Enabling LCD controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) /* enable LCD controller clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (clk_prepare_enable(fbi->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) pr_err("%s: Failed to prepare clock\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (fbi->lccr0 & LCCR0_LCDT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) /* Sequence from 11.7.10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) lcd_writel(fbi, LCCR4, fbi->reg_lccr4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (fbi->lccr0 & LCCR0_SDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) static void pxafb_disable_controller(struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) uint32_t lccr0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) #ifdef CONFIG_FB_PXA_SMARTPANEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (fbi->lccr0 & LCCR0_LCDT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) wait_for_completion_timeout(&fbi->refresh_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) msecs_to_jiffies(200));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) /* Clear LCD Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) lcd_writel(fbi, LCSR, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) lccr0 = lcd_readl(fbi, LCCR0) & ~LCCR0_LDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) lcd_writel(fbi, LCCR0, lccr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) lcd_writel(fbi, LCCR0, lccr0 | LCCR0_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) wait_for_completion_timeout(&fbi->disable_done, msecs_to_jiffies(200));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) /* disable LCD controller clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) clk_disable_unprepare(fbi->clk);
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) * pxafb_handle_irq: Handle 'LCD DONE' interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) struct pxafb_info *fbi = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) unsigned int lccr0, lcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) lcsr = lcd_readl(fbi, LCSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (lcsr & LCSR_LDD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) lccr0 = lcd_readl(fbi, LCCR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) complete(&fbi->disable_done);
^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) #ifdef CONFIG_FB_PXA_SMARTPANEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (lcsr & LCSR_CMD_INT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) complete(&fbi->command_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) lcd_writel(fbi, LCSR, lcsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) #ifdef CONFIG_FB_PXA_OVERLAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) unsigned int lcsr1 = lcd_readl(fbi, LCSR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) if (lcsr1 & LCSR1_BS(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) complete(&fbi->overlay[0].branch_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (lcsr1 & LCSR1_BS(2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) complete(&fbi->overlay[1].branch_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) lcd_writel(fbi, LCSR1, lcsr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * This function must be called from task context only, since it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * sleep when disabling the LCD controller, or if we get two contending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * processes trying to alter state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) u_int old_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) mutex_lock(&fbi->ctrlr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) old_state = fbi->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) * Hack around fbcon initialisation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) if (old_state == C_STARTUP && state == C_REENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) state = C_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) case C_DISABLE_CLKCHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) * Disable controller for clock change. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) * controller is already disabled, then do nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) fbi->state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) /* TODO __pxafb_lcd_power(fbi, 0); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) pxafb_disable_controller(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) case C_DISABLE_PM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) case C_DISABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) * Disable controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) if (old_state != C_DISABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) fbi->state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) __pxafb_backlight_power(fbi, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) __pxafb_lcd_power(fbi, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) if (old_state != C_DISABLE_CLKCHANGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) pxafb_disable_controller(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) case C_ENABLE_CLKCHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) * Enable the controller after clock change. Only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) * do this if we were disabled for the clock change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) if (old_state == C_DISABLE_CLKCHANGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) fbi->state = C_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) pxafb_enable_controller(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) /* TODO __pxafb_lcd_power(fbi, 1); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) case C_REENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * Re-enable the controller only if it was already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * enabled. This is so we reprogram the control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) if (old_state == C_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) __pxafb_lcd_power(fbi, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) pxafb_disable_controller(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) pxafb_enable_controller(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) __pxafb_lcd_power(fbi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) case C_ENABLE_PM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) * Re-enable the controller after PM. This is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) * perfect - think about the case where we were doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) * a clock change, and we suspended half-way through.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) if (old_state != C_DISABLE_PM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) case C_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) * Power up the LCD screen, enable controller, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) * turn on the backlight.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) if (old_state != C_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) fbi->state = C_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) pxafb_enable_controller(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) __pxafb_lcd_power(fbi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) __pxafb_backlight_power(fbi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) mutex_unlock(&fbi->ctrlr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) * Our LCD controller task (which is called when we blank or unblank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) * via keventd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) static void pxafb_task(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) struct pxafb_info *fbi =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) container_of(work, struct pxafb_info, task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) u_int state = xchg(&fbi->task_state, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) set_ctrlr_state(fbi, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * CPU clock speed change handler. We need to adjust the LCD timing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) * parameters when the CPU clock is adjusted by the power management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) * subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * TODO: Determine why f->new != 10*get_lclk_frequency_10khz()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) struct pxafb_info *fbi = TO_INF(nb, freq_transition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) /* TODO struct cpufreq_freqs *f = data; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) u_int pcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) case CPUFREQ_PRECHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) #ifdef CONFIG_FB_PXA_OVERLAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) if (!(fbi->overlay[0].usage || fbi->overlay[1].usage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) case CPUFREQ_POSTCHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) pcd = get_pcd(fbi, fbi->fb.var.pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) set_hsync_time(fbi, pcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) LCCR3_PixClkDiv(pcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) * Power management hooks. Note that we won't be called from IRQ context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * unlike the blank functions above, so we may sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) static int pxafb_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) struct pxafb_info *fbi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) set_ctrlr_state(fbi, C_DISABLE_PM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) static int pxafb_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) struct pxafb_info *fbi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) set_ctrlr_state(fbi, C_ENABLE_PM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) static const struct dev_pm_ops pxafb_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) .suspend = pxafb_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) .resume = pxafb_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) static int pxafb_init_video_memory(struct pxafb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) int size = PAGE_ALIGN(fbi->video_mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) fbi->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) if (fbi->video_mem == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) fbi->video_mem_phys = virt_to_phys(fbi->video_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) fbi->video_mem_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) fbi->fb.fix.smem_start = fbi->video_mem_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) fbi->fb.fix.smem_len = fbi->video_mem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) fbi->fb.screen_base = fbi->video_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) return fbi->video_mem ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) static void pxafb_decode_mach_info(struct pxafb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) struct pxafb_mach_info *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) unsigned int lcd_conn = inf->lcd_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) struct pxafb_mode_info *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) fbi->cmap_inverse = inf->cmap_inverse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) fbi->cmap_static = inf->cmap_static;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) fbi->lccr4 = inf->lccr4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) switch (lcd_conn & LCD_TYPE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) case LCD_TYPE_MONO_STN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) fbi->lccr0 = LCCR0_CMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) case LCD_TYPE_MONO_DSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) fbi->lccr0 = LCCR0_CMS | LCCR0_SDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) case LCD_TYPE_COLOR_STN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) fbi->lccr0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) case LCD_TYPE_COLOR_DSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) fbi->lccr0 = LCCR0_SDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) case LCD_TYPE_COLOR_TFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) fbi->lccr0 = LCCR0_PAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) case LCD_TYPE_SMART_PANEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) fbi->lccr0 = LCCR0_LCDT | LCCR0_PAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) /* fall back to backward compatibility way */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) fbi->lccr0 = inf->lccr0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) fbi->lccr3 = inf->lccr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) goto decode_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (lcd_conn == LCD_MONO_STN_8BPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) fbi->lccr0 |= LCCR0_DPD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) decode_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) pxafb_setmode(&fbi->fb.var, &inf->modes[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) /* decide video memory size as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) * 1. default to mode of maximum resolution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) * 2. allow platform to override
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) * 3. allow module parameter to override
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) for (i = 0, m = &inf->modes[0]; i < inf->num_modes; i++, m++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) fbi->video_mem_size = max_t(size_t, fbi->video_mem_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) m->xres * m->yres * m->bpp / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) if (inf->video_mem_size > fbi->video_mem_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) fbi->video_mem_size = inf->video_mem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) if (video_mem_size > fbi->video_mem_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) fbi->video_mem_size = video_mem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) static struct pxafb_info *pxafb_init_fbinfo(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) struct pxafb_mach_info *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) struct pxafb_info *fbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) /* Alloc the pxafb_info and pseudo_palette in one step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) fbi = devm_kzalloc(dev, sizeof(struct pxafb_info) + sizeof(u32) * 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) if (!fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) fbi->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) fbi->inf = inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) fbi->clk = devm_clk_get(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) if (IS_ERR(fbi->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) return ERR_CAST(fbi->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) strcpy(fbi->fb.fix.id, PXA_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) fbi->fb.fix.type_aux = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) fbi->fb.fix.xpanstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) fbi->fb.fix.ypanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) fbi->fb.fix.ywrapstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) fbi->fb.fix.accel = FB_ACCEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) fbi->fb.var.nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) fbi->fb.var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) fbi->fb.var.height = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) fbi->fb.var.width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) fbi->fb.var.accel_flags = FB_ACCELF_TEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) fbi->fb.fbops = &pxafb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) fbi->fb.flags = FBINFO_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) fbi->fb.node = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) addr = fbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) addr = addr + sizeof(struct pxafb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) fbi->fb.pseudo_palette = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) fbi->state = C_STARTUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) fbi->task_state = (u_char)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) pxafb_decode_mach_info(fbi, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) #ifdef CONFIG_FB_PXA_OVERLAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) /* place overlay(s) on top of base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) if (pxafb_overlay_supported())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) fbi->lccr0 |= LCCR0_OUC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) init_waitqueue_head(&fbi->ctrlr_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) INIT_WORK(&fbi->task, pxafb_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) mutex_init(&fbi->ctrlr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) init_completion(&fbi->disable_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) return fbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) #ifdef CONFIG_FB_PXA_PARAMETERS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) static int parse_opt_mode(struct device *dev, const char *this_opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) struct pxafb_mach_info *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) const char *name = this_opt+5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) unsigned int namelen = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) int res_specified = 0, bpp_specified = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) unsigned int xres = 0, yres = 0, bpp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) int yres_specified = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) for (i = namelen-1; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) switch (name[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) case '-':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) namelen = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) if (!bpp_specified && !yres_specified) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) bpp = simple_strtoul(&name[i+1], NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) bpp_specified = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) if (!yres_specified) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) yres = simple_strtoul(&name[i+1], NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) yres_specified = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) case '0' ... '9':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) if (i < 0 && yres_specified) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) xres = simple_strtoul(name, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) res_specified = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) if (res_specified) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) inf->modes[0].xres = xres; inf->modes[0].yres = yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) if (bpp_specified)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) inf->modes[0].bpp = bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) dev_info(dev, "overriding bit depth: %d\n", bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) dev_err(dev, "Depth %d is not valid\n", bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) static int parse_opt(struct device *dev, char *this_opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) struct pxafb_mach_info *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) struct pxafb_mode_info *mode = &inf->modes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) char s[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) s[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) if (!strncmp(this_opt, "vmem:", 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) video_mem_size = memparse(this_opt + 5, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) } else if (!strncmp(this_opt, "mode:", 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) return parse_opt_mode(dev, this_opt, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) } else if (!strncmp(this_opt, "pixclock:", 9)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) mode->pixclock = simple_strtoul(this_opt+9, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) sprintf(s, "pixclock: %ld\n", mode->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) } else if (!strncmp(this_opt, "left:", 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) mode->left_margin = simple_strtoul(this_opt+5, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) sprintf(s, "left: %u\n", mode->left_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) } else if (!strncmp(this_opt, "right:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) mode->right_margin = simple_strtoul(this_opt+6, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) sprintf(s, "right: %u\n", mode->right_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) } else if (!strncmp(this_opt, "upper:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) mode->upper_margin = simple_strtoul(this_opt+6, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) sprintf(s, "upper: %u\n", mode->upper_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) } else if (!strncmp(this_opt, "lower:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) mode->lower_margin = simple_strtoul(this_opt+6, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) sprintf(s, "lower: %u\n", mode->lower_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) } else if (!strncmp(this_opt, "hsynclen:", 9)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) mode->hsync_len = simple_strtoul(this_opt+9, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) sprintf(s, "hsynclen: %u\n", mode->hsync_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) } else if (!strncmp(this_opt, "vsynclen:", 9)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) mode->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) sprintf(s, "vsynclen: %u\n", mode->vsync_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) } else if (!strncmp(this_opt, "hsync:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) sprintf(s, "hsync: Active Low\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) sprintf(s, "hsync: Active High\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) mode->sync |= FB_SYNC_HOR_HIGH_ACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) } else if (!strncmp(this_opt, "vsync:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) sprintf(s, "vsync: Active Low\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) sprintf(s, "vsync: Active High\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) mode->sync |= FB_SYNC_VERT_HIGH_ACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) } else if (!strncmp(this_opt, "dpc:", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) sprintf(s, "double pixel clock: false\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) inf->lccr3 &= ~LCCR3_DPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) sprintf(s, "double pixel clock: true\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) inf->lccr3 |= LCCR3_DPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) } else if (!strncmp(this_opt, "outputen:", 9)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) sprintf(s, "output enable: active low\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) sprintf(s, "output enable: active high\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) sprintf(s, "pixel clock polarity: falling edge\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) sprintf(s, "pixel clock polarity: rising edge\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) } else if (!strncmp(this_opt, "color", 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) } else if (!strncmp(this_opt, "mono", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) } else if (!strncmp(this_opt, "active", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) } else if (!strncmp(this_opt, "passive", 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) } else if (!strncmp(this_opt, "single", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) } else if (!strncmp(this_opt, "dual", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) } else if (!strncmp(this_opt, "4pix", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) } else if (!strncmp(this_opt, "8pix", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) dev_err(dev, "unknown option: %s\n", this_opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) if (s[0] != '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) dev_info(dev, "override %s", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) static int pxafb_parse_options(struct device *dev, char *options,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) struct pxafb_mach_info *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) char *this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) if (!options || !*options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) dev_dbg(dev, "options are \"%s\"\n", options ? options : "null");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) /* could be made table driven or similar?... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) while ((this_opt = strsep(&options, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) ret = parse_opt(dev, this_opt, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) static char g_options[256] = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) static int __init pxafb_setup_options(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) char *options = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) if (fb_get_options("pxafb", &options))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) if (options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) strlcpy(g_options, options, sizeof(g_options));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) #define pxafb_setup_options() (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) module_param_string(options, g_options, sizeof(g_options), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.rst)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) #define pxafb_parse_options(...) (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) #define pxafb_setup_options() (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) #ifdef DEBUG_VAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) /* Check for various illegal bit-combinations. Currently only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) * a warning is given. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) static void pxafb_check_options(struct device *dev, struct pxafb_mach_info *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) if (inf->lcd_conn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) dev_warn(dev, "machine LCCR0 setting contains "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) "illegal bits: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) dev_warn(dev, "machine LCCR3 setting contains "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) "illegal bits: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) if (inf->lccr0 & LCCR0_DPD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) dev_warn(dev, "Double Pixel Data (DPD) mode is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) "only valid in passive mono"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) " single panel mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) dev_warn(dev, "Dual panel only valid in passive mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) (inf->modes->upper_margin || inf->modes->lower_margin))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) dev_warn(dev, "Upper and lower margins must be 0 in "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) "passive mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) #define pxafb_check_options(...) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) #if defined(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) static const char * const lcd_types[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) "unknown", "mono-stn", "mono-dstn", "color-stn", "color-dstn",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) "color-tft", "smart-panel", NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) static int of_get_pxafb_display(struct device *dev, struct device_node *disp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) struct pxafb_mach_info *info, u32 bus_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) struct display_timings *timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) struct videomode vm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) int i, ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) const char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) ret = of_property_read_string(disp, "lcd-type", &s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) s = "color-tft";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) i = match_string(lcd_types, -1, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) if (i < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) dev_err(dev, "lcd-type %s is unknown\n", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) info->lcd_conn |= LCD_CONN_TYPE(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) info->lcd_conn |= LCD_CONN_WIDTH(bus_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) timings = of_get_display_timings(disp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) if (!timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) info->modes = devm_kcalloc(dev, timings->num_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) sizeof(info->modes[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) if (!info->modes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) info->num_modes = timings->num_timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) for (i = 0; i < timings->num_timings; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) ret = videomode_from_timings(timings, &vm, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) dev_err(dev, "videomode_from_timings %d failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) i, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) if (vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) info->lcd_conn |= LCD_PCLK_EDGE_RISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) info->lcd_conn |= LCD_PCLK_EDGE_FALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) if (vm.flags & DISPLAY_FLAGS_DE_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) info->lcd_conn |= LCD_BIAS_ACTIVE_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) if (vm.flags & DISPLAY_FLAGS_DE_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) info->lcd_conn |= LCD_BIAS_ACTIVE_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) if (vm.flags & DISPLAY_FLAGS_HSYNC_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) info->modes[i].sync |= FB_SYNC_HOR_HIGH_ACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) info->modes[i].sync |= FB_SYNC_VERT_HIGH_ACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) info->modes[i].pixclock = 1000000000UL / (vm.pixelclock / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) info->modes[i].xres = vm.hactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) info->modes[i].yres = vm.vactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) info->modes[i].hsync_len = vm.hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) info->modes[i].left_margin = vm.hback_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) info->modes[i].right_margin = vm.hfront_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) info->modes[i].vsync_len = vm.vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) info->modes[i].upper_margin = vm.vback_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) info->modes[i].lower_margin = vm.vfront_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) display_timings_release(timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) static int of_get_pxafb_mode_info(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) struct pxafb_mach_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) struct device_node *display, *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) u32 bus_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) np = of_graph_get_next_endpoint(dev->of_node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) dev_err(dev, "could not find endpoint\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) ret = of_property_read_u32(np, "bus-width", &bus_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) dev_err(dev, "no bus-width specified: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) display = of_graph_get_remote_port_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) if (!display) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) dev_err(dev, "no display defined\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) ret = of_get_pxafb_display(dev, display, info, bus_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) of_node_put(display);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) for (i = 0; i < info->num_modes; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) info->modes[i].bpp = bus_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) static struct pxafb_mach_info *of_pxafb_of_mach_info(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) struct pxafb_mach_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) if (!dev->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) ret = of_get_pxafb_mode_info(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) * On purpose, neither lccrX registers nor video memory size can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) * specified through device-tree, they are considered more a debug hack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) * available through command line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) return info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) static struct pxafb_mach_info *of_pxafb_of_mach_info(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) static int pxafb_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) struct pxafb_info *fbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) struct pxafb_mach_info *inf, *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) int i, irq, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) dev_dbg(&dev->dev, "pxafb_probe\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) pdata = dev_get_platdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) inf = devm_kmalloc(&dev->dev, sizeof(*inf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) if (!inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) if (pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) *inf = *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) inf->modes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) devm_kmalloc_array(&dev->dev, pdata->num_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) sizeof(inf->modes[0]), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) if (!inf->modes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) for (i = 0; i < inf->num_modes; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) inf->modes[i] = pdata->modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) inf = of_pxafb_of_mach_info(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) if (IS_ERR_OR_NULL(inf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) ret = pxafb_parse_options(&dev->dev, g_options, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) pxafb_check_options(&dev->dev, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) inf->modes->xres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) inf->modes->yres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) inf->modes->bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) if (inf->modes->xres == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) inf->modes->yres == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) inf->modes->bpp == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) dev_err(&dev->dev, "Invalid resolution or bit depth\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) fbi = pxafb_init_fbinfo(&dev->dev, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) if (IS_ERR(fbi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) ret = PTR_ERR(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) if (cpu_is_pxa3xx() && inf->acceleration_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) fbi->fb.fix.accel = FB_ACCEL_PXA3XX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) fbi->backlight_power = inf->pxafb_backlight_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) fbi->lcd_power = inf->pxafb_lcd_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) fbi->lcd_supply = devm_regulator_get_optional(&dev->dev, "lcd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) if (IS_ERR(fbi->lcd_supply)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) if (PTR_ERR(fbi->lcd_supply) == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) fbi->lcd_supply = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) fbi->mmio_base = devm_platform_ioremap_resource(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) if (IS_ERR(fbi->mmio_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) dev_err(&dev->dev, "failed to get I/O memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) ret = PTR_ERR(fbi->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) fbi->dma_buff_size = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) fbi->dma_buff = dma_alloc_coherent(fbi->dev, fbi->dma_buff_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) &fbi->dma_buff_phys, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) if (fbi->dma_buff == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) dev_err(&dev->dev, "failed to allocate memory for DMA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) ret = pxafb_init_video_memory(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) goto failed_free_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) irq = platform_get_irq(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) dev_err(&dev->dev, "no IRQ defined\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) goto failed_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) ret = devm_request_irq(&dev->dev, irq, pxafb_handle_irq, 0, "LCD", fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) dev_err(&dev->dev, "request_irq failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) goto failed_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) ret = pxafb_smart_init(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) dev_err(&dev->dev, "failed to initialize smartpanel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) goto failed_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) * This makes sure that our colour bitfield
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) * descriptors are correctly initialised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) dev_err(&dev->dev, "failed to get suitable mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) goto failed_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) ret = pxafb_set_par(&fbi->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) dev_err(&dev->dev, "Failed to set parameters\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) goto failed_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) platform_set_drvdata(dev, fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) ret = register_framebuffer(&fbi->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) dev_err(&dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) "Failed to register framebuffer device: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) goto failed_free_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) pxafb_overlay_init(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) fbi->freq_transition.notifier_call = pxafb_freq_transition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) cpufreq_register_notifier(&fbi->freq_transition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) CPUFREQ_TRANSITION_NOTIFIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) * Ok, now enable the LCD controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) set_ctrlr_state(fbi, C_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) failed_free_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) if (fbi->fb.cmap.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) fb_dealloc_cmap(&fbi->fb.cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) failed_free_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) free_pages_exact(fbi->video_mem, fbi->video_mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) failed_free_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) dma_free_coherent(&dev->dev, fbi->dma_buff_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) fbi->dma_buff, fbi->dma_buff_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) static int pxafb_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) struct pxafb_info *fbi = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) if (!fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) info = &fbi->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) pxafb_overlay_exit(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) pxafb_disable_controller(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) if (fbi->fb.cmap.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) fb_dealloc_cmap(&fbi->fb.cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) free_pages_exact(fbi->video_mem, fbi->video_mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) dma_free_coherent(&dev->dev, fbi->dma_buff_size, fbi->dma_buff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) fbi->dma_buff_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) static const struct of_device_id pxafb_of_dev_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) { .compatible = "marvell,pxa270-lcdc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) { .compatible = "marvell,pxa300-lcdc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) { .compatible = "marvell,pxa2xx-lcdc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) MODULE_DEVICE_TABLE(of, pxafb_of_dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) static struct platform_driver pxafb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) .probe = pxafb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) .remove = pxafb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) .name = "pxa2xx-fb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) .of_match_table = pxafb_of_dev_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) .pm = &pxafb_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) static int __init pxafb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if (pxafb_setup_options())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) return platform_driver_register(&pxafb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) static void __exit pxafb_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) platform_driver_unregister(&pxafb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) module_init(pxafb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) module_exit(pxafb_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) MODULE_LICENSE("GPL");