diff options
author | Koen Kooi <koen@openembedded.org> | 2008-09-04 16:39:33 +0000 |
---|---|---|
committer | Koen Kooi <koen@openembedded.org> | 2008-09-04 16:39:33 +0000 |
commit | 7a66e7a528dd38a5ea363c30f7110967b6cdd03c (patch) | |
tree | b1bfa7bb4555aec907eea4cd17377829d0894964 /packages/linux/linux-omap | |
parent | 474a816e54c0c5e3135e05eb91022024e1e437b5 (diff) |
linux-omap: a new recipe to build omap1, omap2 and omap3 kernels
Diffstat (limited to 'packages/linux/linux-omap')
43 files changed, 5005 insertions, 0 deletions
diff --git a/packages/linux/linux-omap/.mtn2git_empty b/packages/linux/linux-omap/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-omap/.mtn2git_empty diff --git a/packages/linux/linux-omap/000-mru-make-video-mode-selcatable.diff b/packages/linux/linux-omap/000-mru-make-video-mode-selcatable.diff new file mode 100644 index 0000000000..e36aeb5cff --- /dev/null +++ b/packages/linux/linux-omap/000-mru-make-video-mode-selcatable.diff @@ -0,0 +1,155 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Mon, 18 Aug 2008 22:55:09 +0000 (+0100) +Subject: OMAP: Make video mode commandline-selectable from pre-defined list +X-Git-Tag: beagle-9 +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=c76a61167997a1dc680c421b1cdb753dfd492b0a + +OMAP: Make video mode commandline-selectable from pre-defined list + +This adds a (small) list of video modes and allows one to be +selected with video=omapfb:mode:name on the command line, +overriding the defaults from lcd_*.c. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h +index a4a84f3..92e9ffd 100644 +--- a/arch/arm/plat-omap/include/mach/omapfb.h ++++ b/arch/arm/plat-omap/include/mach/omapfb.h +@@ -192,6 +192,20 @@ enum omapfb_update_mode { + + struct omapfb_device; + ++struct video_mode { ++ const char *name; ++ int x_res, y_res; ++ int pixel_clock; /* In kHz */ ++ int hsw; /* Horizontal synchronization ++ pulse width */ ++ int hfp; /* Horizontal front porch */ ++ int hbp; /* Horizontal back porch */ ++ int vsw; /* Vertical synchronization ++ pulse width */ ++ int vfp; /* Vertical front porch */ ++ int vbp; /* Vertical back porch */ ++}; ++ + struct lcd_panel { + const char *name; + int config; /* TFT/STN, signal inversion */ +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 24242b9..f2229b1 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -40,6 +40,7 @@ static unsigned long def_vxres; + static unsigned long def_vyres; + static unsigned int def_rotate; + static unsigned int def_mirror; ++static int def_mode = -1; + + #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE + static int manual_update = 1; +@@ -80,6 +81,57 @@ static struct caps_table_struct color_caps[] = { + { 1 << OMAPFB_COLOR_YUY422, "YUY422", }, + }; + ++static const struct video_mode video_modes[] = { ++ { ++ .name = "1280x720@50", ++ .x_res = 1280, ++ .y_res = 720, ++ .hfp = 440, ++ .hsw = 40, ++ .hbp = 220, ++ .vfp = 20, ++ .vsw = 5, ++ .vbp = 5, ++ .pixel_clock = 74250, ++ }, ++ { ++ .name = "1280x720@60", ++ .x_res = 1280, ++ .y_res = 720, ++ .hfp = 110, ++ .hsw = 40, ++ .hbp = 220, ++ .vfp = 20, ++ .vsw = 5, ++ .vbp = 5, ++ .pixel_clock = 74250, ++ }, ++ { ++ .name = "1920x1080@24", ++ .x_res = 1920, ++ .y_res = 1080, ++ .hfp = 148, ++ .hsw = 44, ++ .hbp = 638, ++ .vfp = 36, ++ .vsw = 5, ++ .vbp = 4, ++ .pixel_clock = 74160, ++ }, ++ { ++ .name = "1920x1080@25", ++ .x_res = 1920, ++ .y_res = 1080, ++ .hfp = 148, ++ .hsw = 44, ++ .hbp = 528, ++ .vfp = 36, ++ .vsw = 5, ++ .vbp = 4, ++ .pixel_clock = 74250, ++ } ++}; ++ + /* + * --------------------------------------------------------------------------- + * LCD panel +@@ -1711,6 +1763,18 @@ static int omapfb_do_probe(struct platform_device *pdev, + goto cleanup; + } + ++ if (def_mode != -1) { ++ fbdev->panel->x_res = video_modes[def_mode].x_res; ++ fbdev->panel->y_res = video_modes[def_mode].y_res; ++ fbdev->panel->pixel_clock = video_modes[def_mode].pixel_clock; ++ fbdev->panel->hsw = video_modes[def_mode].hsw; ++ fbdev->panel->hfp = video_modes[def_mode].hfp; ++ fbdev->panel->hbp = video_modes[def_mode].hbp; ++ fbdev->panel->vsw = video_modes[def_mode].vsw; ++ fbdev->panel->vfp = video_modes[def_mode].vfp; ++ fbdev->panel->vbp = video_modes[def_mode].vbp; ++ } ++ + r = fbdev->panel->init(fbdev->panel, fbdev); + if (r) + goto cleanup; +@@ -1867,6 +1931,16 @@ static struct platform_driver omapfb_driver = { + }, + }; + ++static int __init omapfb_find_mode(char *mode) ++{ ++ int i; ++ ++ for (i = 0; i < sizeof(video_modes)/sizeof(video_modes[0]); i++) ++ if (!strcmp(mode, video_modes[i].name)) ++ return i; ++ return -1; ++} ++ + #ifndef MODULE + + /* Process kernel command line parameters */ +@@ -1915,6 +1989,8 @@ static int __init omapfb_setup(char *options) + def_mirror = (simple_strtoul(this_opt + 7, NULL, 0)); + else if (!strncmp(this_opt, "manual_update", 13)) + manual_update = 1; ++ else if (!strncmp(this_opt, "mode:", 5)) ++ def_mode = omapfb_find_mode(this_opt + 5); + else { + pr_debug("omapfb: invalid option\n"); + r = -1; diff --git a/packages/linux/linux-omap/0001-ASoC-OMAP-Add-basic-support-for-OMAP34xx-in-McBSP.patch b/packages/linux/linux-omap/0001-ASoC-OMAP-Add-basic-support-for-OMAP34xx-in-McBSP.patch new file mode 100644 index 0000000000..6e31ead2bd --- /dev/null +++ b/packages/linux/linux-omap/0001-ASoC-OMAP-Add-basic-support-for-OMAP34xx-in-McBSP.patch @@ -0,0 +1,55 @@ +From a1dbb6dd28e9815a307b87b8d96dcf371d6cfd58 Mon Sep 17 00:00:00 2001 +From: Jarkko Nikula <jarkko.nikula@nokia.com> +Date: Mon, 19 May 2008 13:24:41 +0300 +Subject: [PATCH] ASoC: OMAP: Add basic support for OMAP34xx in McBSP DAI driver + +This adds support for OMAP34xx McBSP port 1 and 2. + +Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com> +--- + sound/soc/omap/omap-mcbsp.c | 20 +++++++++++++++++++- + 1 files changed, 19 insertions(+), 1 deletions(-) + +diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c +index 40d87e6..8e6ec9d 100644 +--- a/sound/soc/omap/omap-mcbsp.c ++++ b/sound/soc/omap/omap-mcbsp.c +@@ -99,6 +99,21 @@ static const unsigned long omap2420_mcbsp_port[][2] = { + static const int omap2420_dma_reqs[][2] = {}; + static const unsigned long omap2420_mcbsp_port[][2] = {}; + #endif ++#if defined(CONFIG_ARCH_OMAP34XX) ++static const int omap34xx_dma_reqs[][2] = { ++ { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, ++ { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, ++}; ++static const unsigned long omap34xx_mcbsp_port[][2] = { ++ { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR2, ++ OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR2 }, ++ { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR2, ++ OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR2 }, ++}; ++#else ++static const int omap34xx_dma_reqs[][2] = {}; ++static const unsigned long omap34xx_mcbsp_port[][2] = {}; ++#endif + + static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) + { +@@ -169,9 +184,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, + } else if (cpu_is_omap2420()) { + dma = omap2420_dma_reqs[bus_id][substream->stream]; + port = omap2420_mcbsp_port[bus_id][substream->stream]; ++ } else if (cpu_is_omap343x()) { ++ dma = omap34xx_dma_reqs[bus_id][substream->stream]; ++ port = omap34xx_mcbsp_port[bus_id][substream->stream]; + } else { + /* +- * TODO: Add support for 2430 and 3430 ++ * TODO: Add support for 2430 + */ + return -ENODEV; + } +-- +1.5.5.1 + diff --git a/packages/linux/linux-omap/001-mru-enable-overlay.diff b/packages/linux/linux-omap/001-mru-enable-overlay.diff new file mode 100644 index 0000000000..8666c4ac9a --- /dev/null +++ b/packages/linux/linux-omap/001-mru-enable-overlay.diff @@ -0,0 +1,113 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Thu, 28 Aug 2008 21:20:39 +0000 (+0100) +Subject: OMAP: Enable overlay optimisation when possible +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=5a7378bb691e76ce247f39f79e1a928166f1aed9 + +OMAP: Enable overlay optimisation when possible +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index 7c525f5..1d56ee0 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -315,6 +315,60 @@ void omap_dispc_enable_digit_out(int enable) + } + EXPORT_SYMBOL(omap_dispc_enable_digit_out); + ++#define MIN(a, b) ((a)<(b)?(a):(b)) ++#define MAX(a, b) ((a)>(b)?(a):(b)) ++ ++static void setup_overlay_opt(void) ++{ ++ struct fb_info **fbi = dispc.fbdev->fb_info; ++ struct omapfb_plane_struct *gfx, *vid; ++ struct fb_var_screeninfo *gvar; ++ unsigned gx, gx2, gy, gy2, gw, gh; ++ unsigned vx, vx2, vy, vy2, vw, vh; ++ unsigned bpp, skip; ++ static unsigned last_skip; ++ ++ if (!fbi[0] || !fbi[1]) ++ return; ++ ++ gfx = fbi[0]->par; ++ vid = fbi[1]->par; ++ gvar = &fbi[0]->var; ++ ++ gx = gfx->info.pos_x; ++ gy = gfx->info.pos_y; ++ gw = gfx->info.out_width; ++ gh = gfx->info.out_height; ++ vx = vid->info.pos_x; ++ vy = vid->info.pos_y; ++ vw = vid->info.out_width; ++ vh = vid->info.out_height; ++ gx2 = gx + gw; ++ gy2 = gy + gh; ++ vx2 = vx + vw; ++ vy2 = vy + vh; ++ bpp = gvar->bits_per_pixel / 8; ++ ++ if (!gfx->info.enabled || !vid->info.enabled || ++ dispc.color_key.key_type != OMAPFB_COLOR_KEY_DISABLED) { ++ skip = 0; ++ } else if (vx <= gx && vx2 >= gx2) { ++ unsigned y = MIN(gy2, vy2) - MAX(gy, vy); ++ skip = y * gvar->xres_virtual * bpp; ++ } else if (vx <= gx || vx2 >= gx2) { ++ unsigned x = MIN(gx2, vx2) - MAX(gx, vx); ++ skip = x * bpp; ++ } else { ++ skip = vw * bpp + 1; ++ } ++ ++ if (skip != last_skip) { ++ last_skip = skip; ++ dispc_write_reg(DISPC_GFX_WINDOW_SKIP, skip); ++ MOD_REG_FLD(DISPC_CONTROL, 1<<12, !!skip<<12); ++ } ++} ++ + static inline int _setup_plane(int plane, int channel_out, + u32 paddr, int screen_width, + int pos_x, int pos_y, int width, int height, +@@ -437,6 +491,9 @@ static inline int _setup_plane(int plane, int channel_out, + + dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1); + ++ if (plane < 2) ++ setup_overlay_opt(); ++ + MOD_REG_FLD(DISPC_CONTROL, 1<<5, 1<<5); + + return height * screen_width * bpp / 8; +@@ -586,13 +643,19 @@ static int omap_dispc_enable_plane(int plane, int enable) + const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES, + DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, + DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; +- unsigned overlay_opt = plane & !!enable & !dispc.color_key.key_type; ++ struct omapfb_plane_struct *pi; ++ + if ((unsigned int)plane > dispc.mem_desc.region_cnt) + return -EINVAL; + ++ pi = dispc.fbdev->fb_info[plane]->par; ++ pi->info.enabled = enable; ++ + enable_lcd_clocks(1); + MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0); +- MOD_REG_FLD(DISPC_CONTROL, 1<<12 | 1<<5, overlay_opt<<12 | 1<<5); ++ if (plane < 2) ++ setup_overlay_opt(); ++ MOD_REG_FLD(DISPC_CONTROL, 1<<5, 1<<5); + enable_lcd_clocks(0); + + return 0; +@@ -636,6 +699,7 @@ static int omap_dispc_set_color_key(struct omapfb_color_key *ck) + if (val != 0) + dispc_write_reg(tr_reg, ck->trans_key); + dispc_write_reg(df_reg, ck->background); ++ setup_overlay_opt(); + enable_lcd_clocks(0); + + dispc.color_key = *ck; diff --git a/packages/linux/linux-omap/001-sakoman-twl4030-asoc.diff b/packages/linux/linux-omap/001-sakoman-twl4030-asoc.diff new file mode 100644 index 0000000000..d9f028a90c --- /dev/null +++ b/packages/linux/linux-omap/001-sakoman-twl4030-asoc.diff @@ -0,0 +1,875 @@ +From: Steve Sakoman <steve@sakoman.com> +Date: Thu, 4 Sep 2008 04:32:11 +0000 (-0700) +Subject: SOUND: SOC: CODECS: Add support for the TWL4030 audio codec +X-Git-Url: http://www.sakoman.net/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=commitdiff_plain;h=16fc70d77268043edb76946e86a3d776bad26a45 + +SOUND: SOC: CODECS: Add support for the TWL4030 audio codec +--- + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 1db04a2..2f00e1e 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -50,3 +50,8 @@ config SND_SOC_CS4270_VD33_ERRATA + config SND_SOC_TLV320AIC3X + tristate + depends on I2C ++ ++config SND_SOC_TWL4030 ++ tristate ++ depends on SND_SOC && I2C ++ +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index d7b97ab..a519ced 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -10,6 +10,7 @@ snd-soc-wm9712-objs := wm9712.o + snd-soc-wm9713-objs := wm9713.o + snd-soc-cs4270-objs := cs4270.o + snd-soc-tlv320aic3x-objs := tlv320aic3x.o ++snd-soc-twl4030-objs := twl4030.o + + obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o + obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o +@@ -23,3 +24,4 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o + obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o + obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o + obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o ++obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o +diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c +new file mode 100644 +index 0000000..683b8a1 +--- /dev/null ++++ b/sound/soc/codecs/twl4030.c +@@ -0,0 +1,628 @@ ++/* ++ * ALSA SoC TWL4030 codec driver ++ * ++ * Author: Steve Sakoman, <steve@sakoman.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/pm.h> ++#include <linux/i2c.h> ++#include <linux/platform_device.h> ++#include <linux/i2c/twl4030.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++#include <sound/initval.h> ++ ++#include "twl4030.h" ++ ++/* ++ * twl4030 register cache & default register settings ++ */ ++static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { ++ 0x00, /* this register not used */ ++ 0x93, /* REG_CODEC_MODE (0x1) */ ++ 0xc3, /* REG_OPTION (0x2) */ ++ 0x00, /* REG_UNKNOWN (0x3) */ ++ 0x00, /* REG_MICBIAS_CTL (0x4) */ ++ 0x24, /* REG_ANAMICL (0x5) */ ++ 0x04, /* REG_ANAMICR (0x6) */ ++ 0x0a, /* REG_AVADC_CTL (0x7) */ ++ 0x00, /* REG_ADCMICSEL (0x8) */ ++ 0x00, /* REG_DIGMIXING (0x9) */ ++ 0x0c, /* REG_ATXL1PGA (0xA) */ ++ 0x0c, /* REG_ATXR1PGA (0xB) */ ++ 0x00, /* REG_AVTXL2PGA (0xC) */ ++ 0x00, /* REG_AVTXR2PGA (0xD) */ ++ 0x01, /* REG_AUDIO_IF (0xE) */ ++ 0x00, /* REG_VOICE_IF (0xF) */ ++ 0x00, /* REG_ARXR1PGA (0x10) */ ++ 0x00, /* REG_ARXL1PGA (0x11) */ ++ 0x6c, /* REG_ARXR2PGA (0x12) */ ++ 0x6c, /* REG_ARXL2PGA (0x13) */ ++ 0x00, /* REG_VRXPGA (0x14) */ ++ 0x00, /* REG_VSTPGA (0x15) */ ++ 0x00, /* REG_VRX2ARXPGA (0x16) */ ++ 0x0c, /* REG_AVDAC_CTL (0x17) */ ++ 0x00, /* REG_ARX2VTXPGA (0x18) */ ++ 0x00, /* REG_ARXL1_APGA_CTL (0x19) */ ++ 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */ ++ 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */ ++ 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */ ++ 0x00, /* REG_ATX2ARXPGA (0x1D) */ ++ 0x00, /* REG_BT_IF (0x1E) */ ++ 0x00, /* REG_BTPGA (0x1F) */ ++ 0x00, /* REG_BTSTPGA (0x20) */ ++ 0x00, /* REG_EAR_CTL (0x21) */ ++ 0x24, /* REG_HS_SEL (0x22) */ ++ 0x0a, /* REG_HS_GAIN_SET (0x23) */ ++ 0x00, /* REG_HS_POPN_SET (0x24) */ ++ 0x00, /* REG_PREDL_CTL (0x25) */ ++ 0x00, /* REG_PREDR_CTL (0x26) */ ++ 0x00, /* REG_PRECKL_CTL (0x27) */ ++ 0x00, /* REG_PRECKR_CTL (0x28) */ ++ 0x00, /* REG_HFL_CTL (0x29) */ ++ 0x00, /* REG_HFR_CTL (0x2A) */ ++ 0x00, /* REG_ALC_CTL (0x2B) */ ++ 0x00, /* REG_ALC_SET1 (0x2C) */ ++ 0x00, /* REG_ALC_SET2 (0x2D) */ ++ 0x00, /* REG_BOOST_CTL (0x2E) */ ++ 0x01, /* REG_SOFTVOL_CTL (0x2F) */ ++ 0x00, /* REG_DTMF_FREQSEL (0x30) */ ++ 0x00, /* REG_DTMF_TONEXT1H (0x31) */ ++ 0x00, /* REG_DTMF_TONEXT1L (0x32) */ ++ 0x00, /* REG_DTMF_TONEXT2H (0x33) */ ++ 0x00, /* REG_DTMF_TONEXT2L (0x34) */ ++ 0x00, /* REG_DTMF_TONOFF (0x35) */ ++ 0x00, /* REG_DTMF_WANONOFF (0x36) */ ++ 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */ ++ 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */ ++ 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */ ++ 0x16, /* REG_APLL_CTL (0x3A) */ ++ 0x00, /* REG_DTMF_CTL (0x3B) */ ++ 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */ ++ 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */ ++ 0x00, /* REG_MISC_SET_1 (0x3E) */ ++ 0x00, /* REG_PCMBTMUX (0x3F) */ ++ 0x00, /* not used (0x40) */ ++ 0x00, /* not used (0x41) */ ++ 0x00, /* not used (0x42) */ ++ 0x00, /* REG_RX_PATH_SEL (0x43) */ ++ 0x00, /* REG_VDL_APGA_CTL (0x44) */ ++ 0x00, /* REG_VIBRA_CTL (0x45) */ ++ 0x00, /* REG_VIBRA_SET (0x46) */ ++ 0x00, /* REG_VIBRA_PWM_SET (0x47) */ ++ 0x00, /* REG_ANAMIC_GAIN (0x48) */ ++ 0x00, /* REG_MISC_SET_2 (0x49) */ ++}; ++ ++static void twl4030_dump_registers(void) ++{ ++ int i = 0; ++ u8 data; ++ ++ printk(KERN_INFO "TWL 4030 Register dump for Audio Module\n"); ++ ++ for (i = REG_CODEC_MODE; i <= REG_MISC_SET_2; i++) { ++ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &data, i); ++ printk(KERN_INFO "Register[0x%02x]=0x%02x\n", i, data); ++ } ++} ++ ++/* ++ * read twl4030 register cache ++ */ ++static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, ++ unsigned int reg) ++{ ++ u8 *cache = codec->reg_cache; ++ ++ return cache[reg]; ++} ++ ++/* ++ * write twl4030 register cache ++ */ ++static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec, ++ u8 reg, u8 value) ++{ ++ u8 *cache = codec->reg_cache; ++ ++ if (reg >= TWL4030_CACHEREGNUM) ++ return; ++ cache[reg] = value; ++} ++ ++/* ++ * write to the twl4030 register space ++ */ ++static int twl4030_write(struct snd_soc_codec *codec, ++ unsigned int reg, unsigned int value) ++{ ++ twl4030_write_reg_cache(codec, reg, value); ++ return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); ++} ++ ++static void twl4030_init_chip(struct snd_soc_codec *codec) ++{ ++ int i; ++ u8 byte; ++ ++ /* clear CODECPDZ prior to setting register defaults */ ++ twl4030_write(codec, REG_CODEC_MODE, ++ twl4030_reg[REG_CODEC_MODE] & ~CODECPDZ); ++ ++ udelay(10); ++ ++ /* set all audio section registers to reasonable defaults */ ++ for (i = REG_OPTION; i <= REG_MISC_SET_2; i++) ++ twl4030_write(codec, i, twl4030_reg[i]); ++ ++} ++ ++static const struct snd_kcontrol_new twl4030_snd_controls[] = { ++ SOC_DOUBLE_R("Master Playback Volume", ++ REG_ARXL2PGA, REG_ARXR2PGA, ++ 0, 127, 0), ++ SOC_DOUBLE_R("Capture Volume", ++ REG_ATXL1PGA, REG_ATXR1PGA, ++ 0, 127, 0), ++}; ++ ++/* add non dapm controls */ ++static int twl4030_add_controls(struct snd_soc_codec *codec) ++{ ++ int err, i; ++ ++ for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) { ++ err = snd_ctl_add(codec->card, ++ snd_soc_cnew(&twl4030_snd_controls[i], ++ codec, NULL)); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { ++ SND_SOC_DAPM_INPUT("INL"), ++ SND_SOC_DAPM_INPUT("INR"), ++ ++ SND_SOC_DAPM_OUTPUT("OUTL"), ++ SND_SOC_DAPM_OUTPUT("OUTR"), ++ ++ SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0), ++ ++ SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0), ++}; ++ ++static const struct snd_soc_dapm_route intercon[] = { ++ /* outputs */ ++ {"OUTL", NULL, "DACL"}, ++ {"OUTR", NULL, "DACR"}, ++ ++ /* inputs */ ++ {"ADCL", NULL, "INL"}, ++ {"ADCR", NULL, "INR"}, ++}; ++ ++static int twl4030_add_widgets(struct snd_soc_codec *codec) ++{ ++ snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets, ++ ARRAY_SIZE(twl4030_dapm_widgets)); ++ ++ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); ++ ++ snd_soc_dapm_new_widgets(codec); ++ return 0; ++} ++ ++static void twl4030_power_up(struct snd_soc_codec *codec) ++{ ++ u8 mode, byte, popn, hsgain; ++ ++ /* set CODECPDZ to turn on codec */ ++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE); ++ twl4030_write(codec, REG_CODEC_MODE, mode | CODECPDZ); ++ udelay(10); ++ ++ /* initiate offset cancellation */ ++ twl4030_write(codec, REG_ANAMICL, ++ twl4030_reg[REG_ANAMICL] | CNCL_OFFSET_START); ++ ++ /* wait for offset cancellation to complete */ ++ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, REG_ANAMICL); ++ while ((byte & CNCL_OFFSET_START) == CNCL_OFFSET_START) ++ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, ++ &byte, REG_ANAMICL); ++ ++ /* anti-pop when changing analog gain */ ++ twl4030_write(codec, REG_MISC_SET_1, ++ twl4030_reg[REG_MISC_SET_1] | SMOOTH_ANAVOL_EN); ++ ++ /* toggle CODECPDZ as per TRM */ ++ twl4030_write(codec, REG_CODEC_MODE, mode & ~CODECPDZ); ++ udelay(10); ++ ++ twl4030_write(codec, REG_CODEC_MODE, mode | CODECPDZ); ++ udelay(10); ++ ++ /* program anti-pop with bias ramp delay */ ++ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET); ++ popn &= RAMP_DELAY; ++ popn |= RAMP_DELAY_645MS; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++ popn |= VMID_EN; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++ ++ /* enable output stage and gain setting */ ++ hsgain = HSR_GAIN_0DB | HSL_GAIN_0DB; ++ twl4030_write(codec, REG_HS_GAIN_SET, hsgain); ++ ++ /* enable anti-pop ramp */ ++ popn |= RAMP_EN; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++} ++ ++static void twl4030_power_down(struct snd_soc_codec *codec) ++{ ++ u8 popn, hsgain, mode; ++ ++ /* disable anti-pop ramp */ ++ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET); ++ popn &= ~RAMP_EN; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++ ++ /* disable output stage and gain setting */ ++ hsgain = HSR_GAIN_PWR_DOWN | HSL_GAIN_PWR_DOWN; ++ twl4030_write(codec, REG_HS_GAIN_SET, hsgain); ++ ++ /* disable bias out */ ++ popn &= ~VMID_EN; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++ ++ /* power down */ ++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE); ++ twl4030_write(codec, REG_CODEC_MODE, mode & ~CODECPDZ); ++ ++ udelay(10); ++} ++ ++static int twl4030_set_bias_level(struct snd_soc_codec *codec, ++ enum snd_soc_bias_level level) ++{ ++ switch (level) { ++ case SND_SOC_BIAS_ON: ++ twl4030_power_up(codec); ++ break; ++ case SND_SOC_BIAS_PREPARE: ++ break; ++ case SND_SOC_BIAS_STANDBY: ++ twl4030_power_down(codec); ++ break; ++ case SND_SOC_BIAS_OFF: ++ twl4030_power_down(codec); ++ break; ++ } ++ codec->bias_level = level; ++ ++ return 0; ++} ++ ++static int twl4030_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_device *socdev = rtd->socdev; ++ struct snd_soc_codec *codec = socdev->codec; ++ u8 mode, old_mode, format, old_format; ++ ++ ++ /* bit rate */ ++ old_mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE) & ~CODECPDZ; ++ mode = old_mode; ++ mode &= ~APLL_RATE; ++ switch (params_rate(params)) { ++ case 44100: ++ mode |= APLL_RATE_44100; ++ break; ++ case 48000: ++ mode |= APLL_RATE_48000; ++ break; ++ default: ++ printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n", ++ params_rate(params)); ++ return -EINVAL; ++ } ++ ++ if (mode != old_mode) { ++ /* change rate and turn codec back on */ ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ mode |= CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ } ++ ++ /* sample size */ ++ old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF); ++ format = old_format; ++ format &= ~DATA_WIDTH; ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ format |= DATA_WIDTH_16S_16W; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ format |= DATA_WIDTH_32S_24W; ++ break; ++ default: ++ printk(KERN_ERR "TWL4030 hw params: unknown format %d\n", ++ params_format(params)); ++ return -EINVAL; ++ } ++ ++ if (format != old_format) { ++ ++ /* clear CODECPDZ before changing format (codec requirement) */ ++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE); ++ mode &= ~CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ ++ /* change format */ ++ twl4030_write(codec, REG_AUDIO_IF, format); ++ ++ /* set CODECPDZ afterwards */ ++ mode |= CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ } ++ return 0; ++} ++ ++static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, ++ int clk_id, unsigned int freq, int dir) ++{ ++ struct snd_soc_codec *codec = codec_dai->codec; ++ u8 infreq; ++ ++ switch (freq) { ++ case 19200000: ++ infreq = APLL_INFREQ_19200KHZ; ++ break; ++ case 26000000: ++ infreq = APLL_INFREQ_26000KHZ; ++ break; ++ case 38400000: ++ infreq = APLL_INFREQ_38400KHZ; ++ break; ++ default: ++ printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", ++ freq); ++ return -EINVAL; ++ } ++ ++ infreq |= APLL_EN; ++ twl4030_write(codec, REG_APLL_CTL, infreq); ++ ++ return 0; ++} ++ ++static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, ++ unsigned int fmt) ++{ ++ struct snd_soc_codec *codec = codec_dai->codec; ++ u8 mode, old_format, format; ++ ++ /* get format */ ++ old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF); ++ format = old_format; ++ ++ /* set master/slave audio interface */ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBM_CFM: ++ format &= ~(AIF_SLAVE_EN); ++ format |= CLK256FS_EN; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFS: ++ format &= ~(CLK256FS_EN); ++ format |= AIF_SLAVE_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* interface format */ ++ format &= ~AIF_FORMAT; ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ format |= AIF_FORMAT_CODEC; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (format != old_format) { ++ ++ /* clear CODECPDZ before changing format (codec requirement) */ ++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE); ++ mode &= ~CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ ++ /* change format */ ++ twl4030_write(codec, REG_AUDIO_IF, format); ++ ++ /* set CODECPDZ afterwards */ ++ mode |= CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ } ++ ++ return 0; ++} ++ ++#define TWL4030_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) ++#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) ++ ++struct snd_soc_dai twl4030_dai = { ++ .name = "twl4030", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = TWL4030_RATES, ++ .formats = TWL4030_FORMATS,}, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = TWL4030_RATES, ++ .formats = TWL4030_FORMATS,}, ++ .ops = { ++ .hw_params = twl4030_hw_params, ++ }, ++ .dai_ops = { ++ .set_sysclk = twl4030_set_dai_sysclk, ++ .set_fmt = twl4030_set_dai_fmt, ++ } ++}; ++EXPORT_SYMBOL_GPL(twl4030_dai); ++ ++static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec = socdev->codec; ++ ++ twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); ++ ++ return 0; ++} ++ ++static int twl4030_resume(struct platform_device *pdev) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec = socdev->codec; ++ ++ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ++ twl4030_set_bias_level(codec, codec->suspend_bias_level); ++ return 0; ++} ++ ++/* ++ * initialize the driver ++ * register the mixer and dsp interfaces with the kernel ++ */ ++ ++static int twl4030_init(struct snd_soc_device *socdev) ++{ ++ struct snd_soc_codec *codec = socdev->codec; ++ int ret = 0; ++ ++ printk(KERN_INFO "TWL4030 Audio Codec init \n"); ++ ++ codec->name = "twl4030"; ++ codec->owner = THIS_MODULE; ++ codec->read = twl4030_read_reg_cache; ++ codec->write = twl4030_write; ++ codec->set_bias_level = twl4030_set_bias_level; ++ codec->dai = &twl4030_dai; ++ codec->num_dai = 1; ++ codec->reg_cache_size = sizeof(twl4030_reg); ++ codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), ++ GFP_KERNEL); ++ if (codec->reg_cache == NULL) ++ return -ENOMEM; ++ ++ /* register pcms */ ++ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); ++ if (ret < 0) { ++ printk(KERN_ERR "twl4030: failed to create pcms\n"); ++ goto pcm_err; ++ } ++ ++ twl4030_init_chip(codec); ++ ++ /* power on device */ ++ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ++ ++ twl4030_add_controls(codec); ++ twl4030_add_widgets(codec); ++ ++ ret = snd_soc_register_card(socdev); ++ if (ret < 0) { ++ printk(KERN_ERR "twl4030: failed to register card\n"); ++ goto card_err; ++ } ++ ++ return ret; ++ ++card_err: ++ snd_soc_free_pcms(socdev); ++ snd_soc_dapm_free(socdev); ++pcm_err: ++ kfree(codec->reg_cache); ++ return ret; ++} ++ ++static struct snd_soc_device *twl4030_socdev; ++ ++static int twl4030_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec; ++ ++ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); ++ if (codec == NULL) ++ return -ENOMEM; ++ ++ socdev->codec = codec; ++ mutex_init(&codec->mutex); ++ INIT_LIST_HEAD(&codec->dapm_widgets); ++ INIT_LIST_HEAD(&codec->dapm_paths); ++ ++ twl4030_socdev = socdev; ++ twl4030_init(socdev); ++ ++ return 0; ++} ++ ++static int twl4030_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec = socdev->codec; ++ ++ printk(KERN_INFO "TWL4030 Audio Codec remove\n"); ++ kfree(codec); ++ ++ return 0; ++} ++ ++struct snd_soc_codec_device soc_codec_dev_twl4030 = { ++ .probe = twl4030_probe, ++ .remove = twl4030_remove, ++ .suspend = twl4030_suspend, ++ .resume = twl4030_resume, ++}; ++EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); ++ ++MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); ++MODULE_AUTHOR("Steve Sakoman"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h +new file mode 100644 +index 0000000..013dabc +--- /dev/null ++++ b/sound/soc/codecs/twl4030.h +@@ -0,0 +1,197 @@ ++/* ++ * ALSA SoC TWL4030 codec driver ++ * ++ * Author: Steve Sakoman <steve@sakoman.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#ifndef __TWL4030_AUDIO_H__ ++#define __TWL4030_AUDIO_H__ ++ ++#define REG_CODEC_MODE 0x1 ++#define REG_OPTION 0x2 ++#define REG_UNKNOWN 0x3 ++#define REG_MICBIAS_CTL 0x4 ++#define REG_ANAMICL 0x5 ++#define REG_ANAMICR 0x6 ++#define REG_AVADC_CTL 0x7 ++#define REG_ADCMICSEL 0x8 ++#define REG_DIGMIXING 0x9 ++#define REG_ATXL1PGA 0xA ++#define REG_ATXR1PGA 0xB ++#define REG_AVTXL2PGA 0xC ++#define REG_AVTXR2PGA 0xD ++#define REG_AUDIO_IF 0xE ++#define REG_VOICE_IF 0xF ++#define REG_ARXR1PGA 0x10 ++#define REG_ARXL1PGA 0x11 ++#define REG_ARXR2PGA 0x12 ++#define REG_ARXL2PGA 0x13 ++#define REG_VRXPGA 0x14 ++#define REG_VSTPGA 0x15 ++#define REG_VRX2ARXPGA 0x16 ++#define REG_AVDAC_CTL 0x17 ++#define REG_ARX2VTXPGA 0x18 ++#define REG_ARXL1_APGA_CTL 0x19 ++#define REG_ARXR1_APGA_CTL 0x1A ++#define REG_ARXL2_APGA_CTL 0x1B ++#define REG_ARXR2_APGA_CTL 0x1C ++#define REG_ATX2ARXPGA 0x1D ++#define REG_BT_IF 0x1E ++#define REG_BTPGA 0x1F ++#define REG_BTSTPGA 0x20 ++#define REG_EAR_CTL 0x21 ++#define REG_HS_SEL 0x22 ++#define REG_HS_GAIN_SET 0x23 ++#define REG_HS_POPN_SET 0x24 ++#define REG_PREDL_CTL 0x25 ++#define REG_PREDR_CTL 0x26 ++#define REG_PRECKL_CTL 0x27 ++#define REG_PRECKR_CTL 0x28 ++#define REG_HFL_CTL 0x29 ++#define REG_HFR_CTL 0x2A ++#define REG_ALC_CTL 0x2B ++#define REG_ALC_SET1 0x2C ++#define REG_ALC_SET2 0x2D ++#define REG_BOOST_CTL 0x2E ++#define REG_SOFTVOL_CTL 0x2F ++#define REG_DTMF_FREQSEL 0x30 ++#define REG_DTMF_TONEXT1H 0x31 ++#define REG_DTMF_TONEXT1L 0x32 ++#define REG_DTMF_TONEXT2H 0x33 ++#define REG_DTMF_TONEXT2L 0x34 ++#define REG_DTMF_TONOFF 0x35 ++#define REG_DTMF_WANONOFF 0x36 ++#define REG_I2S_RX_SCRAMBLE_H 0x37 ++#define REG_I2S_RX_SCRAMBLE_M 0x38 ++#define REG_I2S_RX_SCRAMBLE_L 0x39 ++#define REG_APLL_CTL 0x3A ++#define REG_DTMF_CTL 0x3B ++#define REG_DTMF_PGA_CTL2 0x3C ++#define REG_DTMF_PGA_CTL1 0x3D ++#define REG_MISC_SET_1 0x3E ++#define REG_PCMBTMUX 0x3F ++#define REG_RX_PATH_SEL 0x43 ++#define REG_VDL_APGA_CTL 0x44 ++#define REG_VIBRA_CTL 0x45 ++#define REG_VIBRA_SET 0x46 ++#define REG_VIBRA_PWM_SET 0x47 ++#define REG_ANAMIC_GAIN 0x48 ++#define REG_MISC_SET_2 0x49 ++ ++#define TWL4030_CACHEREGNUM (REG_MISC_SET_2 + 1) ++ ++/* Bitfield Definitions */ ++ ++/* CODEC_MODE (0x01) Fields */ ++ ++#define APLL_RATE 0xF0 ++#define APLL_RATE_8000 0x00 ++#define APLL_RATE_11025 0x10 ++#define APLL_RATE_12000 0x20 ++#define APLL_RATE_16000 0x40 ++#define APLL_RATE_22050 0x50 ++#define APLL_RATE_24000 0x60 ++#define APLL_RATE_32000 0x80 ++#define APLL_RATE_44100 0x90 ++#define APLL_RATE_48000 0xA0 ++#define SEL_16K 0x04 ++#define CODECPDZ 0x02 ++#define OPT_MODE 0x01 ++ ++/* ANAMICL (0x05) Fields */ ++#define CNCL_OFFSET_START 0x80 ++#define OFFSET_CNCL_SEL 0x60 ++#define OFFSET_CNCL_SEL_ARX1 0x00 ++#define OFFSET_CNCL_SEL_ARX2 0x20 ++#define OFFSET_CNCL_SEL_VRX 0x40 ++#define OFFSET_CNCL_SEL_ALL 0x60 ++#define MICAMPL_EN 0x10 ++#define CKMIC_EN 0x08 ++#define AUXL_EN 0x04 ++#define HSMIC_EN 0x02 ++#define MAINMIC_EN 0x01 ++ ++/* ANAMICR (0x06) Fields */ ++#define MICAMPR_EN 0x10 ++#define AUXR_EN 0x04 ++#define SUBMIC_EN 0x01 ++ ++/* AUDIO_IF (0x0E) Fields */ ++ ++#define AIF_SLAVE_EN 0x80 ++#define DATA_WIDTH 0x60 ++#define DATA_WIDTH_16S_16W 0x00 ++#define DATA_WIDTH_32S_16W 0x40 ++#define DATA_WIDTH_32S_24W 0x60 ++#define AIF_FORMAT 0x18 ++#define AIF_FORMAT_CODEC 0x00 ++#define AIF_FORMAT_LEFT 0x08 ++#define AIF_FORMAT_RIGHT 0x10 ++#define AIF_FORMAT_TDM 0x18 ++#define AIF_TRI_EN 0x04 ++#define CLK256FS_EN 0x02 ++#define AIF_EN 0x01 ++ ++/* HS_GAIN_SET (0x23) Fields */ ++ ++#define HSR_GAIN 0x0C ++#define HSR_GAIN_PWR_DOWN 0x00 ++#define HSR_GAIN_PLUS_6DB 0x04 ++#define HSR_GAIN_0DB 0x08 ++#define HSR_GAIN_MINUS_6DB 0x0C ++#define HSL_GAIN 0x03 ++#define HSL_GAIN_PWR_DOWN 0x00 ++#define HSL_GAIN_PLUS_6DB 0x01 ++#define HSL_GAIN_0DB 0x02 ++#define HSL_GAIN_MINUS_6DB 0x03 ++ ++/* HS_POPN_SET (0x24) Fields */ ++ ++#define VMID_EN 0x40 ++#define EXTMUTE 0x20 ++#define RAMP_DELAY 0x1C ++#define RAMP_DELAY_20MS 0x00 ++#define RAMP_DELAY_40MS 0x04 ++#define RAMP_DELAY_81MS 0x08 ++#define RAMP_DELAY_161MS 0x0C ++#define RAMP_DELAY_323MS 0x10 ++#define RAMP_DELAY_645MS 0x14 ++#define RAMP_DELAY_1291MS 0x18 ++#define RAMP_DELAY_2581MS 0x1C ++#define RAMP_EN 0x02 ++ ++/* APLL_CTL (0x3A) Fields */ ++ ++#define APLL_EN 0x10 ++#define APLL_INFREQ 0x0F ++#define APLL_INFREQ_19200KHZ 0x05 ++#define APLL_INFREQ_26000KHZ 0x06 ++#define APLL_INFREQ_38400KHZ 0x0F ++ ++/* REG_MISC_SET_1 (0x3E) Fields */ ++ ++#define CLK64_EN 0x80 ++#define SCRAMBLE_EN 0x40 ++#define FMLOOP_EN 0x20 ++#define SMOOTH_ANAVOL_EN 0x02 ++#define DIGMIC_LR_SWAP_EN 0x01 ++ ++extern struct snd_soc_dai twl4030_dai; ++extern struct snd_soc_codec_device soc_codec_dev_twl4030; ++ ++#endif /* End of __TWL4030_AUDIO_H__ */ diff --git a/packages/linux/linux-omap/002-mru-set-default-800x600.diff b/packages/linux/linux-omap/002-mru-set-default-800x600.diff new file mode 100644 index 0000000000..b45f849ba4 --- /dev/null +++ b/packages/linux/linux-omap/002-mru-set-default-800x600.diff @@ -0,0 +1,61 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Fri, 29 Aug 2008 00:42:02 +0000 (+0100) +Subject: OMAP: Set Beagleboard default video mode to 800x600 60Hz +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=17b546e6d65aee124a2b691727cdb2c1dcadaec5 + +OMAP: Set Beagleboard default video mode to 800x600 60Hz + +This sets the default video mode on the Beagleboard to +800x600 60Hz VESA CVT 0.48M3-R, 16bpp. This is compatible +with a wider range of monitors than the old default values. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c +index 9637735..f2861ec 100644 +--- a/drivers/video/omap/lcd_omap3beagle.c ++++ b/drivers/video/omap/lcd_omap3beagle.c +@@ -31,10 +31,6 @@ + + #define LCD_PANEL_ENABLE_GPIO 170 + +-#define LCD_XRES 1024 +-#define LCD_YRES 768 +-#define LCD_PIXCLOCK 64000 /* in kHz */ +- + static int omap3beagle_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) + { +@@ -65,19 +61,19 @@ static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel) + struct lcd_panel omap3beagle_panel = { + .name = "omap3beagle", + .config = OMAP_LCDC_PANEL_TFT, +- +- .bpp = 24, ++ .bpp = 16, + .data_lines = 24, +- .x_res = LCD_XRES, +- .y_res = LCD_YRES, +- .hsw = 3, /* hsync_len (4) - 1 */ +- .hfp = 3, /* right_margin (4) - 1 */ +- .hbp = 39, /* left_margin (40) - 1 */ +- .vsw = 1, /* vsync_len (2) - 1 */ +- .vfp = 2, /* lower_margin */ +- .vbp = 7, /* upper_margin (8) - 1 */ +- +- .pixel_clock = LCD_PIXCLOCK, ++ ++ /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */ ++ .x_res = 800, ++ .y_res = 600, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 11, ++ .pixel_clock = 35500, + + .init = omap3beagle_panel_init, + .cleanup = omap3beagle_panel_cleanup, diff --git a/packages/linux/linux-omap/003-mru-omapfb-more-video-modes.diff b/packages/linux/linux-omap/003-mru-omapfb-more-video-modes.diff new file mode 100644 index 0000000000..34241640eb --- /dev/null +++ b/packages/linux/linux-omap/003-mru-omapfb-more-video-modes.diff @@ -0,0 +1,317 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Fri, 29 Aug 2008 08:28:31 +0000 (+0100) +Subject: OMAP: Add more video modes, and make the default configurable +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=ef272670f19fac8fb0ceb82933927dab1fb496b7 + +OMAP: Add more video modes, and make the default configurable +--- + +diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h +index 92e9ffd..a4a84f3 100644 +--- a/arch/arm/plat-omap/include/mach/omapfb.h ++++ b/arch/arm/plat-omap/include/mach/omapfb.h +@@ -192,20 +192,6 @@ enum omapfb_update_mode { + + struct omapfb_device; + +-struct video_mode { +- const char *name; +- int x_res, y_res; +- int pixel_clock; /* In kHz */ +- int hsw; /* Horizontal synchronization +- pulse width */ +- int hfp; /* Horizontal front porch */ +- int hbp; /* Horizontal back porch */ +- int vsw; /* Vertical synchronization +- pulse width */ +- int vfp; /* Vertical front porch */ +- int vbp; /* Vertical back porch */ +-}; +- + struct lcd_panel { + const char *name; + int config; /* TFT/STN, signal inversion */ +diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig +index bdeb8fb..9977e80 100644 +--- a/drivers/video/omap/Kconfig ++++ b/drivers/video/omap/Kconfig +@@ -7,6 +7,14 @@ config FB_OMAP + help + Frame buffer driver for OMAP based boards. + ++config FB_OMAP_VIDEO_MODE ++ string "Default video mode" ++ depends on FB_OMAP ++ help ++ Enter video mode name to use if none is specified on the kernel ++ command line. If left blank, board-specific default timings ++ will be used. See omapfb_main.c for a list of valid mode names. ++ + config FB_OMAP_LCDC_EXTERNAL + bool "External LCD controller support" + depends on FB_OMAP +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index f2229b1..2e53d8f 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -33,6 +33,20 @@ + + #define MODULE_NAME "omapfb" + ++struct video_mode { ++ const char *name; ++ int x_res, y_res; ++ int pixel_clock; /* In kHz */ ++ int hsw; /* Horizontal synchronization ++ pulse width */ ++ int hfp; /* Horizontal front porch */ ++ int hbp; /* Horizontal back porch */ ++ int vsw; /* Vertical synchronization ++ pulse width */ ++ int vfp; /* Vertical front porch */ ++ int vbp; /* Vertical back porch */ ++}; ++ + static unsigned int def_accel; + static unsigned long def_vram[OMAPFB_PLANE_NUM]; + static int def_vram_cnt; +@@ -40,7 +54,7 @@ static unsigned long def_vxres; + static unsigned long def_vyres; + static unsigned int def_rotate; + static unsigned int def_mirror; +-static int def_mode = -1; ++static char def_mode[16] = CONFIG_FB_OMAP_VIDEO_MODE; + + #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE + static int manual_update = 1; +@@ -51,6 +65,7 @@ static int manual_update; + static struct platform_device *fbdev_pdev; + static struct lcd_panel *fbdev_panel; + static struct omapfb_device *omapfb_dev; ++static struct video_mode video_mode; + + struct caps_table_struct { + unsigned long flag; +@@ -81,9 +96,88 @@ static struct caps_table_struct color_caps[] = { + { 1 << OMAPFB_COLOR_YUY422, "YUY422", }, + }; + +-static const struct video_mode video_modes[] = { ++static struct video_mode video_modes[] __initdata = { ++ { ++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ ++ .name = "640x480@60", ++ .x_res = 640, ++ .y_res = 480, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 7, ++ .pixel_clock = 23500, ++ }, ++ { ++ /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */ ++ .name = "800x600@60", ++ .x_res = 800, ++ .y_res = 600, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 11, ++ .pixel_clock = 35500, ++ }, ++ { ++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */ ++ .name = "1024x768@60", ++ .x_res = 1024, ++ .y_res = 768, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 15, ++ .pixel_clock = 56000, ++ }, ++ { ++ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */ ++ .name = "1280x720@60", ++ .x_res = 1280, ++ .y_res = 720, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 5, ++ .vbp = 13, ++ .pixel_clock = 64000, ++ }, ++ { ++ /* 720 x 480 @ 60 Hz CEA-861 Format 3 */ ++ .name = "480p60", ++ .x_res = 720, ++ .y_res = 480, ++ .hfp = 16, ++ .hsw = 62, ++ .hbp = 60, ++ .vfp = 9, ++ .vsw = 6, ++ .vbp = 30, ++ .pixel_clock = 27027, ++ }, ++ { ++ /* 720 x 576 @ 60 Hz CEA-861 Format 18 */ ++ .name = "576p50", ++ .x_res = 720, ++ .y_res = 576, ++ .hfp = 12, ++ .hsw = 64, ++ .hbp = 68, ++ .vfp = 5, ++ .vsw = 5, ++ .vbp = 39, ++ .pixel_clock = 27000, ++ }, + { +- .name = "1280x720@50", ++ /* 1280 x 720 @ 50 Hz CEA-861B Format 19 */ ++ .name = "720p50", + .x_res = 1280, + .y_res = 720, + .hfp = 440, +@@ -95,7 +189,8 @@ static const struct video_mode video_modes[] = { + .pixel_clock = 74250, + }, + { +- .name = "1280x720@60", ++ /* 1280 x 720 @ 60 Hz CEA-861B Format 4 */ ++ .name = "720p60", + .x_res = 1280, + .y_res = 720, + .hfp = 110, +@@ -107,7 +202,8 @@ static const struct video_mode video_modes[] = { + .pixel_clock = 74250, + }, + { +- .name = "1920x1080@24", ++ /* 1920 x 1080 @ 24 Hz CEA-861B Format 32 */ ++ .name = "1080p24", + .x_res = 1920, + .y_res = 1080, + .hfp = 148, +@@ -116,10 +212,11 @@ static const struct video_mode video_modes[] = { + .vfp = 36, + .vsw = 5, + .vbp = 4, +- .pixel_clock = 74160, ++ .pixel_clock = 74250, + }, + { +- .name = "1920x1080@25", ++ /* 1920 x 1080 @ 25 Hz CEA-861B Format 33 */ ++ .name = "1080p25", + .x_res = 1920, + .y_res = 1080, + .hfp = 148, +@@ -129,7 +226,20 @@ static const struct video_mode video_modes[] = { + .vsw = 5, + .vbp = 4, + .pixel_clock = 74250, +- } ++ }, ++ { ++ /* 1920 x 1080 @ 25 Hz CEA-861B Format 34 */ ++ .name = "1080p30", ++ .x_res = 1920, ++ .y_res = 1080, ++ .hfp = 148, ++ .hsw = 44, ++ .hbp = 88, ++ .vfp = 36, ++ .vsw = 5, ++ .vbp = 4, ++ .pixel_clock = 74250, ++ }, + }; + + /* +@@ -1763,16 +1873,18 @@ static int omapfb_do_probe(struct platform_device *pdev, + goto cleanup; + } + +- if (def_mode != -1) { +- fbdev->panel->x_res = video_modes[def_mode].x_res; +- fbdev->panel->y_res = video_modes[def_mode].y_res; +- fbdev->panel->pixel_clock = video_modes[def_mode].pixel_clock; +- fbdev->panel->hsw = video_modes[def_mode].hsw; +- fbdev->panel->hfp = video_modes[def_mode].hfp; +- fbdev->panel->hbp = video_modes[def_mode].hbp; +- fbdev->panel->vsw = video_modes[def_mode].vsw; +- fbdev->panel->vfp = video_modes[def_mode].vfp; +- fbdev->panel->vbp = video_modes[def_mode].vbp; ++ if (video_mode.name) { ++ pr_info("omapfb: using mode %s\n", video_mode.name); ++ ++ fbdev->panel->x_res = video_mode.x_res; ++ fbdev->panel->y_res = video_mode.y_res; ++ fbdev->panel->pixel_clock = video_mode.pixel_clock; ++ fbdev->panel->hsw = video_mode.hsw; ++ fbdev->panel->hfp = video_mode.hfp; ++ fbdev->panel->hbp = video_mode.hbp; ++ fbdev->panel->vsw = video_mode.vsw; ++ fbdev->panel->vfp = video_mode.vfp; ++ fbdev->panel->vbp = video_mode.vbp; + } + + r = fbdev->panel->init(fbdev->panel, fbdev); +@@ -1931,14 +2043,15 @@ static struct platform_driver omapfb_driver = { + }, + }; + +-static int __init omapfb_find_mode(char *mode) ++static void __init omapfb_find_mode(char *name, struct video_mode *vmode) + { + int i; + + for (i = 0; i < sizeof(video_modes)/sizeof(video_modes[0]); i++) +- if (!strcmp(mode, video_modes[i].name)) +- return i; +- return -1; ++ if (!strcmp(name, video_modes[i].name)) { ++ *vmode = video_modes[i]; ++ break; ++ } + } + + #ifndef MODULE +@@ -1990,7 +2103,7 @@ static int __init omapfb_setup(char *options) + else if (!strncmp(this_opt, "manual_update", 13)) + manual_update = 1; + else if (!strncmp(this_opt, "mode:", 5)) +- def_mode = omapfb_find_mode(this_opt + 5); ++ strncpy(def_mode, this_opt + 5, sizeof(def_mode)); + else { + pr_debug("omapfb: invalid option\n"); + r = -1; +@@ -2012,6 +2125,9 @@ static int __init omapfb_init(void) + return -ENODEV; + omapfb_setup(option); + #endif ++ ++ omapfb_find_mode(def_mode, &video_mode); ++ + /* Register the driver with LDM */ + if (platform_driver_register(&omapfb_driver)) { + pr_debug("failed to register omapfb driver\n"); +@@ -2033,6 +2149,7 @@ module_param_named(vyres, def_vyres, long, 0664); + module_param_named(rotate, def_rotate, uint, 0664); + module_param_named(mirror, def_mirror, uint, 0664); + module_param_named(manual_update, manual_update, bool, 0664); ++module_param_string(video_mode, def_mode, sizeof(def_mode), 0664); + + module_init(omapfb_init); + module_exit(omapfb_cleanup); diff --git a/packages/linux/linux-omap/004-mru-export-omapfb-register-panel.diff b/packages/linux/linux-omap/004-mru-export-omapfb-register-panel.diff new file mode 100644 index 0000000000..24ebcdea52 --- /dev/null +++ b/packages/linux/linux-omap/004-mru-export-omapfb-register-panel.diff @@ -0,0 +1,25 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 3 Sep 2008 20:56:03 +0000 (+0100) +Subject: OMAP: Export omapfb_register_panel() +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=44811584aded9e47a83d69ad31002a6bb94730dc + +OMAP: Export omapfb_register_panel() + +This exports omapfb_register_panel() for use by LCD drivers built +as modules. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 2e53d8f..912cb0c 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -1997,6 +1997,7 @@ void omapfb_register_panel(struct lcd_panel *panel) + if (fbdev_pdev != NULL) + omapfb_do_probe(fbdev_pdev, fbdev_panel); + } ++EXPORT_SYMBOL(omapfb_register_panel); + + /* Called when the device is being detached from the driver */ + static int omapfb_remove(struct platform_device *pdev) diff --git a/packages/linux/linux-omap/005-mru-add-omapfb-unregister-panel.diff b/packages/linux/linux-omap/005-mru-add-omapfb-unregister-panel.diff new file mode 100644 index 0000000000..faee384e74 --- /dev/null +++ b/packages/linux/linux-omap/005-mru-add-omapfb-unregister-panel.diff @@ -0,0 +1,67 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 3 Sep 2008 20:57:59 +0000 (+0100) +Subject: OMAP: Add omapfb_unregister_panel() function +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=85b5d3ba7221193cb2315256b69e97f34d2ae3b7 + +OMAP: Add omapfb_unregister_panel() function + +This adds the function omapfb_unregister_panel() for use by LCD +drivers built as modules. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h +index a4a84f3..3ccb076 100644 +--- a/arch/arm/plat-omap/include/mach/omapfb.h ++++ b/arch/arm/plat-omap/include/mach/omapfb.h +@@ -378,6 +378,7 @@ extern struct lcd_ctrl omap2_disp_ctrl; + + extern void omapfb_reserve_sdram(void); + extern void omapfb_register_panel(struct lcd_panel *panel); ++extern void omapfb_unregister_panel(struct lcd_panel *panel); + extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); + extern void omapfb_notify_clients(struct omapfb_device *fbdev, + unsigned long event); +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 912cb0c..6d09e03 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -1736,7 +1736,8 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state) + case 7: + omapfb_unregister_sysfs(fbdev); + case 6: +- fbdev->panel->disable(fbdev->panel); ++ if (fbdev->panel) ++ fbdev->panel->disable(fbdev->panel); + case 5: + omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED); + case 4: +@@ -1744,7 +1745,8 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state) + case 3: + ctrl_cleanup(fbdev); + case 2: +- fbdev->panel->cleanup(fbdev->panel); ++ if (fbdev->panel) ++ fbdev->panel->cleanup(fbdev->panel); + case 1: + dev_set_drvdata(fbdev->dev, NULL); + kfree(fbdev); +@@ -1999,6 +2001,17 @@ void omapfb_register_panel(struct lcd_panel *panel) + } + EXPORT_SYMBOL(omapfb_register_panel); + ++void omapfb_unregister_panel(struct lcd_panel *panel) ++{ ++ BUG_ON(fbdev_panel != panel); ++ ++ panel->disable(panel); ++ ++ omapfb_dev->panel = NULL; ++ fbdev_panel = NULL; ++} ++EXPORT_SYMBOL(omapfb_unregister_panel); ++ + /* Called when the device is being detached from the driver */ + static int omapfb_remove(struct platform_device *pdev) + { diff --git a/packages/linux/linux-omap/006-mru-lcd-as-modules.diff b/packages/linux/linux-omap/006-mru-lcd-as-modules.diff new file mode 100644 index 0000000000..e522b3f7bf --- /dev/null +++ b/packages/linux/linux-omap/006-mru-lcd-as-modules.diff @@ -0,0 +1,174 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 3 Sep 2008 23:05:33 +0000 (+0100) +Subject: OMAP: Build LCD drivers as separate modules +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=127dc3100fe9d25ed2b6c0a056e4160cc05db653 + +OMAP: Build LCD drivers as separate modules + +This enables building the various LCD drivers as modules separate +from omapfb. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig +index 9977e80..93cd760 100644 +--- a/drivers/video/omap/Kconfig ++++ b/drivers/video/omap/Kconfig +@@ -53,6 +53,70 @@ config FB_OMAP_LCD_MIPID + the Mobile Industry Processor Interface DBI-C/DCS + specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) + ++config OMAP_FB_LCD_AMS_DELTA ++ tristate "AMS DELTA LCD support" ++ depends on FB_OMAP && MACH_AMS_DELTA ++ ++config OMAP_FB_LCD_H2 ++ tristate "H2 LCD support" ++ depends on FB_OMAP && MACH_OMAP_H2 ++ ++config OMAP_FB_LCD_H3 ++ tristate "H3 LCD support" ++ depends on FB_OMAP && MACH_OMAP_H3 ++ ++config OMAP_FB_LCD_H4 ++ tristate "OMAP 2420 H4 LCD support" ++ depends on FB_OMAP && MACH_OMAP_H4 ++ ++config OMAP_FB_LCD_PALMTE ++ tristate "PALMTE LCD support" ++ depends on FB_OMAP && MACH_OMAP_PALMTE ++ ++config OMAP_FB_LCD_PALMTT ++ tristate "PALMTT LCD support" ++ depends on FB_OMAP && MACH_OMAP_PALMTT ++ ++config OMAP_FB_LCD_PALMZ71 ++ tristate "PALMZ71 LCD support" ++ depends on FB_OMAP && MACH_OMAP_PALMZ71 ++ ++config OMAP_FB_LCD_INN1610 ++ tristate "INN1610 LCD support" ++ depends on FB_OMAP && ARCH_OMAP16XX && MACH_OMAP_INNOVATOR ++ ++config OMAP_FB_LCD_INN1510 ++ tristate "INN1510 LCD support" ++ depends on FB_OMAP && ARCH_OMAP15XX && MACH_OMAP_INNOVATOR ++ ++config OMAP_FB_LCD_OSK ++ tristate "OSK LCD support" ++ depends on FB_OMAP && MACH_OMAP_OSK ++ ++config OMAP_FB_LCD_SX1 ++ tristate "SX1 LCD support" ++ depends on FB_OMAP && MACH_SX1 ++ ++config OMAP_FB_LCD_APOLLON ++ tristate "OMAP 2420 Apollon LCD support" ++ depends on FB_OMAP && MACH_OMAP_APOLLON ++ ++config OMAP_FB_LCD_2430SDP ++ tristate "OMAP 2430/3430 SDP LCD support" ++ depends on FB_OMAP && (MACH_OMAP_2430SDP || MACH_OMAP_3430SDP) ++ ++config OMAP_FB_LCD_OMAP2EVM ++ tristate "OMAP 2530 EVM LCD support" ++ depends on FB_OMAP && MACH_OMAP2EVM ++ ++config OMAP_FB_LCD_OMAP3EVM ++ tristate "OMAP 3530 EVM LCD support" ++ depends on FB_OMAP && MACH_OMAP3EVM ++ ++config OMAP_FB_LCD_OMAP3BEAGLE ++ tristate "Beagle board DVI port support" ++ depends on FB_OMAP && MACH_OMAP3_BEAGLE ++ + config FB_OMAP_BOOTLOADER_INIT + bool "Check bootloader initialization" + depends on FB_OMAP +diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile +dissimilarity index 64% +index f9b5cd4..dbdcd67 100644 +--- a/drivers/video/omap/Makefile ++++ b/drivers/video/omap/Makefile +@@ -1,40 +1,40 @@ +-# +-# Makefile for the new OMAP framebuffer device driver +-# +- +-obj-$(CONFIG_FB_OMAP) += omapfb.o +- +-objs-yy := omapfb_main.o +- +-objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o +-objs-y$(CONFIG_ARCH_OMAP2) += dispc.o +-objs-y$(CONFIG_ARCH_OMAP3) += dispc.o +- +-objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o +-objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o +- +-objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o +-objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o +- +-objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o +-objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o +-objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o +-objs-y$(CONFIG_MACH_OMAP_H2) += lcd_h2.o +-objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o +-objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o +-objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o +-objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o +-objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o +-objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o +-objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o +- +-objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o +-objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o +-objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o +-objs-y$(CONFIG_MACH_OMAP2EVM) += lcd_omap2evm.o +-objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o +-objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o +-objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o +- +-omapfb-objs := $(objs-yy) +- ++# ++# Makefile for the new OMAP framebuffer device driver ++# ++ ++obj-$(CONFIG_FB_OMAP) += omapfb.o ++ ++objs-yy := omapfb_main.o ++ ++objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o ++objs-y$(CONFIG_ARCH_OMAP2) += dispc.o ++objs-y$(CONFIG_ARCH_OMAP3) += dispc.o ++ ++objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o ++objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o ++ ++objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o ++objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o ++ ++obj-$(CONFIG_OMAP_FB_LCD_AMS_DELTA) += lcd_ams_delta.o ++obj-$(CONFIG_OMAP_FB_LCD_H4) += lcd_h4.o ++obj-$(CONFIG_OMAP_FB_LCD_H3) += lcd_h3.o ++obj-$(CONFIG_OMAP_FB_LCD_H2) += lcd_h2.o ++obj-$(CONFIG_OMAP_FB_LCD_PALMTE) += lcd_palmte.o ++obj-$(CONFIG_OMAP_FB_LCD_PALMTT) += lcd_palmtt.o ++obj-$(CONFIG_OMAP_FB_LCD_PALMZ71) += lcd_palmz71.o ++obj-$(CONFIG_OMAP_FB_LCD_INN1610) += lcd_inn1610.o ++obj-$(CONFIG_OMAP_FB_LCD_INN1510) += lcd_inn1510.o ++obj-$(CONFIG_OMAP_FB_LCD_OSK) += lcd_osk.o ++obj-$(CONFIG_OMAP_FB_LCD_SX1) += lcd_sx1.o ++ ++obj-$(CONFIG_OMAP_FB_LCD_APOLLON) += lcd_apollon.o ++obj-$(CONFIG_OMAP_FB_LCD_2430SDP) += lcd_2430sdp.o ++obj-$(CONFIG_OMAP_FB_LCD_2430SDP) += lcd_2430sdp.o ++obj-$(CONFIG_OMAP_FB_LCD_OMAP2EVM) += lcd_omap2evm.o ++obj-$(CONFIG_OMAP_FB_LCD_OMAP3EVM) += lcd_omap3evm.o ++obj-$(CONFIG_OMAP_FB_LCD_OMAP3BEAGLE) += lcd_omap3beagle.o ++obj-$(CONFIG_OMAP_FB_LCD_MIPID) += lcd_mipid.o ++ ++omapfb-objs := $(objs-yy) ++ diff --git a/packages/linux/linux-omap/007-mru-omapfb-as-module.diff b/packages/linux/linux-omap/007-mru-omapfb-as-module.diff new file mode 100644 index 0000000000..e1eed0d154 --- /dev/null +++ b/packages/linux/linux-omap/007-mru-omapfb-as-module.diff @@ -0,0 +1,50 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 3 Sep 2008 23:10:08 +0000 (+0100) +Subject: OMAP: Fix omapfb built as module +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=ae65001ce247e510121bcda21775263bb4c42e05 + +OMAP: Fix omapfb built as module + +This makes it possible to build omapfb as a module. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index 6187e8f..4213c4f 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -1073,7 +1073,8 @@ static int mmap_kern(struct omapfb_mem_region *region) + pgprot_t pgprot; + unsigned long vaddr; + +- kvma = get_vm_area(region->size, VM_IOREMAP); ++ kvma = __get_vm_area(region->size, VM_IOREMAP, ++ VMALLOC_START, VMALLOC_END); + if (kvma == NULL) { + dev_err(dispc.fbdev->dev, "can't get kernel vm area\n"); + return -ENOMEM; +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 6d09e03..19a1a83 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -2016,12 +2016,15 @@ EXPORT_SYMBOL(omapfb_unregister_panel); + static int omapfb_remove(struct platform_device *pdev) + { + struct omapfb_device *fbdev = platform_get_drvdata(pdev); +- enum omapfb_state saved_state = fbdev->state; + +- /* FIXME: wait till completion of pending events */ ++ if (fbdev) { ++ enum omapfb_state saved_state = fbdev->state; + +- fbdev->state = OMAPFB_DISABLED; +- omapfb_free_resources(fbdev, saved_state); ++ /* FIXME: wait till completion of pending events */ ++ ++ fbdev->state = OMAPFB_DISABLED; ++ omapfb_free_resources(fbdev, saved_state); ++ } + + return 0; + } diff --git a/packages/linux/linux-omap/008-mru-lcd-omap3beagle-license.diff b/packages/linux/linux-omap/008-mru-lcd-omap3beagle-license.diff new file mode 100644 index 0000000000..4f69dd971a --- /dev/null +++ b/packages/linux/linux-omap/008-mru-lcd-omap3beagle-license.diff @@ -0,0 +1,22 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 3 Sep 2008 23:12:03 +0000 (+0100) +Subject: OMAP: Add missing MODULE_LICENSE in lcd_omap3beagle +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=368ba31e3e7dccdcea790c559ad3d3b4a20d924f + +OMAP: Add missing MODULE_LICENSE in lcd_omap3beagle + +This adds a missing MODULE_LICENSE("GPL") in lcd_omap3beagle. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c +index f2861ec..7b63db9 100644 +--- a/drivers/video/omap/lcd_omap3beagle.c ++++ b/drivers/video/omap/lcd_omap3beagle.c +@@ -127,3 +127,5 @@ static void __exit omap3beagle_panel_drv_exit(void) + + module_init(omap3beagle_panel_drv_init); + module_exit(omap3beagle_panel_drv_exit); ++ ++MODULE_LICENSE("GPL"); diff --git a/packages/linux/linux-omap/009-mru-unregister-beagle-lcd.diff b/packages/linux/linux-omap/009-mru-unregister-beagle-lcd.diff new file mode 100644 index 0000000000..c7e94bf3a4 --- /dev/null +++ b/packages/linux/linux-omap/009-mru-unregister-beagle-lcd.diff @@ -0,0 +1,24 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 3 Sep 2008 23:17:06 +0000 (+0100) +Subject: OMAP: Fix unloading lcd_omap3beagle module +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=6db3a4c28c6819047362fc8ac460cf8c124c6074 + +OMAP: Fix unloading lcd_omap3beagle module + +Unregister the panel when unloading the lcd_omap3beagle module. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c +index 7b63db9..32bd988 100644 +--- a/drivers/video/omap/lcd_omap3beagle.c ++++ b/drivers/video/omap/lcd_omap3beagle.c +@@ -90,6 +90,7 @@ static int omap3beagle_panel_probe(struct platform_device *pdev) + + static int omap3beagle_panel_remove(struct platform_device *pdev) + { ++ omapfb_unregister_panel(&omap3beagle_panel); + return 0; + } + diff --git a/packages/linux/linux-omap/01-fix-timing-print.diff b/packages/linux/linux-omap/01-fix-timing-print.diff new file mode 100644 index 0000000000..89fbe3a836 --- /dev/null +++ b/packages/linux/linux-omap/01-fix-timing-print.diff @@ -0,0 +1,23 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Sat, 5 Jul 2008 20:31:56 +0000 (+0100) +Subject: omapfb: fix video timings message +X-Git-Tag: beagle-5~3 +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=2929b75035ebe8702ba2ff2c81b654c487701f64 + +omapfb: fix video timings message +--- + +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 418ed9f..1166a01 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -1789,7 +1789,8 @@ static int omapfb_do_probe(struct platform_device *pdev, + vram, fbdev->mem_desc.region_cnt); + pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz " + "vfreq %lu.%lu Hz\n", +- phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10); ++ phz / 1000, hhz / 10000, hhz % 10000, ++ vhz / 10, vhz % 10); + + return 0; + diff --git a/packages/linux/linux-omap/010-mru-fix-video-mode-param.diff b/packages/linux/linux-omap/010-mru-fix-video-mode-param.diff new file mode 100644 index 0000000000..50d69b8b75 --- /dev/null +++ b/packages/linux/linux-omap/010-mru-fix-video-mode-param.diff @@ -0,0 +1,35 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 3 Sep 2008 23:19:04 +0000 (+0100) +Subject: OMAP: Fix omapfb video mode selection when built as module +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=9bafff77f3028cd170c605c8d883963522c8546c + +OMAP: Fix omapfb video mode selection when built as module + +This fixes the video_mode parameter when omapfb is built as a module. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 19a1a83..e0b3642 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -54,7 +54,7 @@ static unsigned long def_vxres; + static unsigned long def_vyres; + static unsigned int def_rotate; + static unsigned int def_mirror; +-static char def_mode[16] = CONFIG_FB_OMAP_VIDEO_MODE; ++static char def_mode[16]; + + #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE + static int manual_update = 1; +@@ -2143,7 +2143,8 @@ static int __init omapfb_init(void) + omapfb_setup(option); + #endif + +- omapfb_find_mode(def_mode, &video_mode); ++ omapfb_find_mode(def_mode[0]? def_mode : CONFIG_FB_OMAP_VIDEO_MODE, ++ &video_mode); + + /* Register the driver with LDM */ + if (platform_driver_register(&omapfb_driver)) { diff --git a/packages/linux/linux-omap/02-set-clkseld11.diff b/packages/linux/linux-omap/02-set-clkseld11.diff new file mode 100644 index 0000000000..c437f145d3 --- /dev/null +++ b/packages/linux/linux-omap/02-set-clkseld11.diff @@ -0,0 +1,22 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Sat, 5 Jul 2008 20:32:38 +0000 (+0100) +Subject: omap: set CLKSEL_DSS1 to 2 +X-Git-Tag: beagle-5~2 +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=d23f9c3c5c6243b626f7ec4c255469de2536e488 + +omap: set CLKSEL_DSS1 to 2 +--- + +diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c +index 8fdf8f3..04dedec 100644 +--- a/arch/arm/mach-omap2/clock34xx.c ++++ b/arch/arm/mach-omap2/clock34xx.c +@@ -596,6 +596,8 @@ int __init omap2_clk_init(void) + /* u32 clkrate; */ + u32 cpu_clkflg; + ++ __raw_writel(0x1002, io_p2v(0x48004e40)); ++ + /* REVISIT: Ultimately this will be used for multiboot */ + #if 0 + if (cpu_is_omap242x()) { diff --git a/packages/linux/linux-omap/03-enable-overlay-opt.diff b/packages/linux/linux-omap/03-enable-overlay-opt.diff new file mode 100644 index 0000000000..9fa749f5fc --- /dev/null +++ b/packages/linux/linux-omap/03-enable-overlay-opt.diff @@ -0,0 +1,27 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 6 Jul 2008 13:15:36 +0000 (+0100) +Subject: omapfb: enable overlay optimisation when possible +X-Git-Tag: beagle-5~1 +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=a63ac3abdf6781f863112321260fe7a5da757802 + +omapfb: enable overlay optimisation when possible +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index 6aff476..3b36227 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -582,11 +582,13 @@ static int omap_dispc_enable_plane(int plane, int enable) + const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES, + DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, + DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; ++ unsigned overlay_opt = plane & !!enable & !dispc.color_key.key_type; + if ((unsigned int)plane > dispc.mem_desc.region_cnt) + return -EINVAL; + + enable_lcd_clocks(1); + MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0); ++ MOD_REG_FLD(DISPC_CONTROL, 1<<12 | 1<<5, overlay_opt<<12 | 1<<5); + enable_lcd_clocks(0); + + return 0; diff --git a/packages/linux/linux-omap/04-use-pcd.diff b/packages/linux/linux-omap/04-use-pcd.diff new file mode 100644 index 0000000000..bdf8ab5f0b --- /dev/null +++ b/packages/linux/linux-omap/04-use-pcd.diff @@ -0,0 +1,28 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 6 Jul 2008 13:22:54 +0000 (+0100) +Subject: omapfb: use PCD if set in panel config +X-Git-Tag: beagle-5 +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=c8060d36ae156771f00a7a27cabf1b4435c378bd + +omapfb: use PCD if set in panel config +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index 3b36227..4e1a8e3 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -798,7 +798,13 @@ static void set_lcd_timings(void) + l |= panel->acb & 0xff; + dispc_write_reg(DISPC_POL_FREQ, l); + +- calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div); ++ if (panel->pcd) { ++ pck_div = panel->pcd; ++ lck_div = 1; ++ } else { ++ calc_ck_div(is_tft, panel->pixel_clock * 1000, ++ &lck_div, &pck_div); ++ } + + l = dispc_read_reg(DISPC_DIVISOR); + l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8)); diff --git a/packages/linux/linux-omap/05-fix-display-panning.diff b/packages/linux/linux-omap/05-fix-display-panning.diff new file mode 100644 index 0000000000..d3c9fffcda --- /dev/null +++ b/packages/linux/linux-omap/05-fix-display-panning.diff @@ -0,0 +1,45 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Mon, 7 Jul 2008 00:13:00 +0000 (+0100) +Subject: omapfb: fix display panning +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=9fec252c96b0e69bcef0afd9cb9dd72b7179c239 + +omapfb: fix display panning +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index 4e1a8e3..c17371c 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -435,6 +435,8 @@ static inline int _setup_plane(int plane, int channel_out, + + dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1); + ++ MOD_REG_FLD(DISPC_CONTROL, 1<<5, 1<<5); ++ + return height * screen_width * bpp / 8; + } + +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 1166a01..3e4959e 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -206,8 +206,8 @@ static int ctrl_change_mode(struct fb_info *fbi) + struct omapfb_device *fbdev = plane->fbdev; + struct fb_var_screeninfo *var = &fbi->var; + +- offset = var->yoffset * fbi->fix.line_length + +- var->xoffset * var->bits_per_pixel / 8; ++ offset = (var->yoffset * var->xres_virtual + var->xoffset) * ++ var->bits_per_pixel / 8; + + if (fbdev->ctrl->sync) + fbdev->ctrl->sync(); +@@ -423,6 +423,8 @@ static void set_fb_fix(struct fb_info *fbi) + } + fix->accel = FB_ACCEL_OMAP1610; + fix->line_length = var->xres_virtual * bpp / 8; ++ fix->xpanstep = 1; ++ fix->ypanstep = 1; + } + + static int set_color_mode(struct omapfb_plane_struct *plane, diff --git a/packages/linux/linux-omap/06-ensure-fclk.diff b/packages/linux/linux-omap/06-ensure-fclk.diff new file mode 100644 index 0000000000..79871a7208 --- /dev/null +++ b/packages/linux/linux-omap/06-ensure-fclk.diff @@ -0,0 +1,31 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Mon, 7 Jul 2008 23:59:08 +0000 (+0100) +Subject: omapfb: ensure fck/lcd < 173MHz +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=0523ece1bad659c48c66aea364d83f7490e7e5ae + +omapfb: ensure fck/lcd < 173MHz +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index c17371c..85d6cad 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -738,14 +738,16 @@ static void setup_color_conv_coef(void) + MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range); + } + ++#define MAX_FCK_LCD 173000000 ++ + static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div) + { + unsigned long fck, lck; + +- *lck_div = 1; + pck = max(1, pck); + fck = clk_get_rate(dispc.dss1_fck); +- lck = fck; ++ *lck_div = (fck + MAX_FCK_LCD - 1) / MAX_FCK_LCD; ++ lck = fck / *lck_div; + *pck_div = (lck + pck - 1) / pck; + if (is_tft) + *pck_div = max(2, *pck_div); diff --git a/packages/linux/linux-omap/07-set-burst-size.diff b/packages/linux/linux-omap/07-set-burst-size.diff new file mode 100644 index 0000000000..99bd80eae0 --- /dev/null +++ b/packages/linux/linux-omap/07-set-burst-size.diff @@ -0,0 +1,21 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Tue, 8 Jul 2008 18:26:43 +0000 (+0100) +Subject: omapfb: set graphics burst size to 16x32 +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=4f9e415dfcd5613a8de973f6c9878cab959c5869 + +omapfb: set graphics burst size to 16x32 +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index 85d6cad..fd06ca2 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -409,7 +409,7 @@ static inline int _setup_plane(int plane, int channel_out, + l |= cconv_en << 9; + + l &= ~(0x03 << burst_shift); +- l |= DISPC_BURST_8x32 << burst_shift; ++ l |= DISPC_BURST_16x32 << burst_shift; + + l &= ~(1 << chout_shift); + l |= chout_val << chout_shift; diff --git a/packages/linux/linux-omap/16bpp.patch b/packages/linux/linux-omap/16bpp.patch new file mode 100644 index 0000000000..d2bff4b018 --- /dev/null +++ b/packages/linux/linux-omap/16bpp.patch @@ -0,0 +1,137 @@ +diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig +index bdeb8fb..bf256f3 100644 +--- a/drivers/video/omap/Kconfig ++++ b/drivers/video/omap/Kconfig +@@ -7,6 +7,27 @@ config FB_OMAP + help + Frame buffer driver for OMAP based boards. + ++choice ++ depends on FB_OMAP && MACH_OMAP3_BEAGLE ++ prompt "Screen resolution" ++ default FB_OMAP_079M3R ++ help ++ Selected desired screen resolution ++ ++config FB_OMAP_031M3R ++ boolean "640 x 480 @ 60 Hz Reduced blanking" ++ ++config FB_OMAP_048M3R ++ boolean "800 x 600 @ 60 Hz Reduced blanking" ++ ++config FB_OMAP_079M3R ++ boolean "1024 x 768 @ 60 Hz Reduced blanking" ++ ++config FB_OMAP_092M9R ++ boolean "1280 x 720 @ 60 Hz Reduced blanking" ++ ++endchoice ++ + config FB_OMAP_LCDC_EXTERNAL + bool "External LCD controller support" + depends on FB_OMAP +diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c +index 69d4e06..5e098c2 100644 +--- a/drivers/video/omap/lcd_omap3beagle.c ++++ b/drivers/video/omap/lcd_omap3beagle.c +@@ -31,10 +31,6 @@ + + #define LCD_PANEL_ENABLE_GPIO 170 + +-#define LCD_XRES 1024 +-#define LCD_YRES 768 +-#define LCD_PIXCLOCK 64000 /* in kHz */ +- + static int omap3beagle_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) + { +@@ -65,19 +61,76 @@ static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel) + struct lcd_panel omap3beagle_panel = { + .name = "omap3beagle", + .config = OMAP_LCDC_PANEL_TFT, +- +- .bpp = 24, ++ .bpp = 16, + .data_lines = 24, +- .x_res = LCD_XRES, +- .y_res = LCD_YRES, +- .hsw = 3, /* hsync_len (4) - 1 */ +- .hfp = 3, /* right_margin (4) - 1 */ +- .hbp = 39, /* left_margin (40) - 1 */ +- .vsw = 1, /* vsync_len (2) - 1 */ +- .vfp = 2, /* lower_margin */ +- .vbp = 7, /* upper_margin (8) - 1 */ +- +- .pixel_clock = LCD_PIXCLOCK, ++ ++#if defined CONFIG_FB_OMAP_031M3R ++ ++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ ++ .x_res = 640, ++ .y_res = 480, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 7, ++ .pixel_clock = 23500, ++ ++#elif defined CONFIG_FB_OMAP_048M3R ++ ++ /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */ ++ .x_res = 800, ++ .y_res = 600, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 11, ++ .pixel_clock = 35500, ++ ++#elif defined CONFIG_FB_OMAP_079M3R ++ ++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */ ++ .x_res = 1024, ++ .y_res = 768, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 15, ++ .pixel_clock = 56000, ++ ++#elif defined CONFIG_FB_OMAP_092M9R ++ ++ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */ ++ .x_res = 1280, ++ .y_res = 720, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 5, ++ .vbp = 13, ++ .pixel_clock = 64000, ++ ++#else ++ ++ /* use 640 x 480 if no config option */ ++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ ++ .x_res = 640, ++ .y_res = 480, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 7, ++ .pixel_clock = 23500, ++ ++#endif + + .init = omap3beagle_panel_init, + .cleanup = omap3beagle_panel_cleanup, + diff --git a/packages/linux/linux-omap/4bitmmc.diff b/packages/linux/linux-omap/4bitmmc.diff new file mode 100644 index 0000000000..5cd120c544 --- /dev/null +++ b/packages/linux/linux-omap/4bitmmc.diff @@ -0,0 +1,38 @@ +From: Purushotam Kumar <purushotam@ti.com> +Date: Fri, 18 Jul 2008 23:28:57 +0000 (-0700) +Subject: OMAP3:devices.c:Enabling 4-bit for SD card +X-Git-Url: http://www.sakoman.net/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=commitdiff_plain;h=6c4d34031c80ca4b50ffe73a4ef7fe197a760a60 + +OMAP3:devices.c:Enabling 4-bit for SD card + +SD card was working in 1-bit mode.This patch will configure SD card in +4-bit mode and hence performance will increase. + +Signed-off-by: Purushotam Kumar <purushotam@ti.com> +Acked-by: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com> +--- + +diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c +index b83f9a6..d0cfceb 100644 +--- a/arch/arm/plat-omap/devices.c ++++ b/arch/arm/plat-omap/devices.c +@@ -296,13 +296,17 @@ static void __init omap_init_mmc(void) + mmc = &mmc_conf->mmc[0]; + + if (cpu_is_omap2430() || cpu_is_omap34xx()) { +- if (mmc->enabled) ++ if (mmc->enabled) { ++ mmc1_data.conf = *mmc; + (void) platform_device_register(&mmc_omap_device1); ++ } + + #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) + mmc = &mmc_conf->mmc[1]; +- if (mmc->enabled) ++ if (mmc->enabled) { ++ mmc2_data.conf = *mmc; + (void) platform_device_register(&mmc_omap_device2); ++ } + #endif + + return; diff --git a/packages/linux/linux-omap/beagleboard/.mtn2git_empty b/packages/linux/linux-omap/beagleboard/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-omap/beagleboard/.mtn2git_empty diff --git a/packages/linux/linux-omap/cache-display-fix.patch b/packages/linux/linux-omap/cache-display-fix.patch new file mode 100644 index 0000000000..019fd5acf1 --- /dev/null +++ b/packages/linux/linux-omap/cache-display-fix.patch @@ -0,0 +1,238 @@ +On Tue, 2008-07-01 at 06:23 +0100, Dirk Behme wrote: +> Catalin Marinas wrote: +> > But, anyway, if you want a patch, Harry is updating it to a recent +> > kernel. +> +> Any news on this? I think there are some people wanting a patch ;) + +See below for a preliminary patch updated to 2.6.26-rc8. Note that I +don't plan to submit it in its current form but clean it up a bit first. + + +Show the cache type of ARMv7 CPUs + +From: Catalin Marinas <catalin.marinas@arm.com> + +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +--- + + arch/arm/kernel/setup.c | 137 +++++++++++++++++++++++++++++++++++++++++++++- + include/asm-arm/system.h | 18 ++++++ + 2 files changed, 153 insertions(+), 2 deletions(-) + + +diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c +index 5ae0eb2..0cd238d 100644 +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -256,6 +256,24 @@ static const char *proc_arch[] = { + "?(17)", + }; + ++static const char *v7_cache_policy[4] = { ++ "reserved", ++ "AVIVT", ++ "VIPT", ++ "PIPT", ++}; ++ ++static const char *v7_cache_type[8] = { ++ "none", ++ "instruction only", ++ "data only", ++ "separate instruction and data", ++ "unified", ++ "unknown type", ++ "unknown type", ++ "unknown type", ++}; ++ + #define CACHE_TYPE(x) (((x) >> 25) & 15) + #define CACHE_S(x) ((x) & (1 << 24)) + #define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */ +@@ -266,6 +284,22 @@ static const char *proc_arch[] = { + #define CACHE_M(y) ((y) & (1 << 2)) + #define CACHE_LINE(y) ((y) & 3) + ++#define CACHE_TYPE_V7(x) (((x) >> 14) & 3) ++#define CACHE_UNIFIED(x) ((((x) >> 27) & 7)+1) ++#define CACHE_COHERENT(x) ((((x) >> 24) & 7)+1) ++ ++#define CACHE_ID_LEVEL_MASK 7 ++#define CACHE_ID_LEVEL_BITS 3 ++ ++#define CACHE_LINE_V7(v) ((1 << (((v) & 7)+4))) ++#define CACHE_ASSOC_V7(v) ((((v) >> 3) & ((1<<10)-1))+1) ++#define CACHE_SETS_V7(v) ((((v) >> 13) & ((1<<15)-1))+1) ++#define CACHE_SIZE_V7(v) (CACHE_LINE_V7(v)*CACHE_ASSOC_V7(v)*CACHE_SETS_V7(v)) ++#define CACHE_WA_V7(v) (((v) & (1<<28)) != 0) ++#define CACHE_RA_V7(v) (((v) & (1<<29)) != 0) ++#define CACHE_WB_V7(v) (((v) & (1<<30)) != 0) ++#define CACHE_WT_V7(v) (((v) & (1<<31)) != 0) ++ + static inline void dump_cache(const char *prefix, int cpu, unsigned int cache) + { + unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0); +@@ -279,11 +313,57 @@ static inline void dump_cache(const char *prefix, int cpu, unsigned int cache) + CACHE_LINE(cache))); + } + ++static void dump_v7_cache(const char *type, int cpu, unsigned int level) ++{ ++ unsigned int cachesize; ++ ++ write_extended_cpuid(2,0,0,0,level); /* Set the cache size selection register */ ++ write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */ ++ cachesize = read_extended_cpuid(1,0,0,0); ++ ++ printk("CPU%u: %s cache: %d bytes, associativity %d, %d byte lines, %d sets,\n supports%s%s%s%s\n", ++ cpu, type, ++ CACHE_SIZE_V7(cachesize),CACHE_ASSOC_V7(cachesize), ++ CACHE_LINE_V7(cachesize),CACHE_SETS_V7(cachesize), ++ CACHE_WA_V7(cachesize) ? " WA" : "", ++ CACHE_RA_V7(cachesize) ? " RA" : "", ++ CACHE_WB_V7(cachesize) ? " WB" : "", ++ CACHE_WT_V7(cachesize) ? " WT" : ""); ++} ++ + static void __init dump_cpu_info(int cpu) + { + unsigned int info = read_cpuid(CPUID_CACHETYPE); + +- if (info != processor_id) { ++ if (info != processor_id && (info & (1 << 31))) { ++ /* ARMv7 style of cache info register */ ++ unsigned int id = read_extended_cpuid(1,0,0,1); ++ unsigned int level = 0; ++ printk("CPU%u: L1 I %s cache. Caches unified at level %u, coherent at level %u\n", ++ cpu, ++ v7_cache_policy[CACHE_TYPE_V7(info)], ++ CACHE_UNIFIED(id), ++ CACHE_COHERENT(id)); ++ ++ while (id & CACHE_ID_LEVEL_MASK) { ++ printk("CPU%u: Level %u cache is %s\n", ++ cpu, (level >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]); ++ ++ if (id & 1) { ++ /* Dump I at this level */ ++ dump_v7_cache("I", cpu, level | 1); ++ } ++ ++ if (id & (4 | 2)) { ++ /* Dump D or unified at this level */ ++ dump_v7_cache((id & 4) ? "unified" : "D", cpu, level); ++ } ++ ++ /* Next level out */ ++ level += 2; ++ id >>= CACHE_ID_LEVEL_BITS; ++ } ++ } else if (info != processor_id) { + printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT", + cache_types[CACHE_TYPE(info)]); + if (CACHE_S(info)) { +@@ -916,6 +996,30 @@ c_show_cache(struct seq_file *m, const char *type, unsigned int cache) + CACHE_LINE(cache))); + } + ++static void c_show_v7_cache(struct seq_file *m, const char *type, unsigned int levelselect) ++{ ++ unsigned int cachesize; ++ unsigned int level = (levelselect >> 1) + 1; ++ ++ write_extended_cpuid(2,0,0,0,levelselect); /* Set the cache size selection register */ ++ write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */ ++ cachesize = read_extended_cpuid(1,0,0,0); ++ ++ seq_printf(m, "L%u %s size\t\t: %d bytes\n" ++ "L%u %s assoc\t\t: %d\n" ++ "L%u %s line length\t: %d\n" ++ "L%u %s sets\t\t: %d\n" ++ "L%u %s supports\t\t:%s%s%s%s\n", ++ level, type, CACHE_SIZE_V7(cachesize), ++ level, type, CACHE_ASSOC_V7(cachesize), ++ level, type, CACHE_LINE_V7(cachesize), ++ level, type, CACHE_SETS_V7(cachesize), ++ level, type, CACHE_WA_V7(cachesize) ? " WA" : "", ++ CACHE_RA_V7(cachesize) ? " RA" : "", ++ CACHE_WB_V7(cachesize) ? " WB" : "", ++ CACHE_WT_V7(cachesize) ? " WT" : ""); ++} ++ + static int c_show(struct seq_file *m, void *v) + { + int i; +@@ -971,7 +1075,36 @@ static int c_show(struct seq_file *m, void *v) + + { + unsigned int cache_info = read_cpuid(CPUID_CACHETYPE); +- if (cache_info != processor_id) { ++ if (cache_info != processor_id && (cache_info & (1<<31))) { ++ /* V7 style of cache info register */ ++ unsigned int id = read_extended_cpuid(1,0,0,1); ++ unsigned int levelselect = 0; ++ seq_printf(m, "L1 I cache\t:%s\n" ++ "Cache unification level\t: %u\n" ++ "Cache coherency level\t: %u\n", ++ v7_cache_policy[CACHE_TYPE_V7(cache_info)], ++ CACHE_UNIFIED(id), ++ CACHE_COHERENT(id)); ++ ++ while (id & CACHE_ID_LEVEL_MASK) { ++ seq_printf(m, "Level %u cache\t\t: %s\n", ++ (levelselect >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]); ++ ++ if (id & 1) { ++ /* Dump I at this level */ ++ c_show_v7_cache(m, "I", levelselect | 1); ++ } ++ ++ if (id & (4 | 2)) { ++ /* Dump D or unified at this level */ ++ c_show_v7_cache(m, (id & 4) ? "cache" : "D", levelselect); ++ } ++ ++ /* Next level out */ ++ levelselect += 2; ++ id >>= CACHE_ID_LEVEL_BITS; ++ } ++ } else if (cache_info != processor_id) { + seq_printf(m, "Cache type\t: %s\n" + "Cache clean\t: %s\n" + "Cache lockdown\t: %s\n" +diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h +index 514af79..704738e 100644 +--- a/arch/arm/include/asm/system.h ++++ b/arch/arm/include/asm/system.h +@@ -74,6 +74,24 @@ + : "cc"); \ + __val; \ + }) ++#define read_extended_cpuid(op1,op2,op3,op4) \ ++ ({ \ ++ unsigned int __val; \ ++ asm("mrc p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \ ++ : "=r" (__val) \ ++ : \ ++ : "cc"); \ ++ __val; \ ++ }) ++ ++#define write_extended_cpuid(op1,op2,op3,op4,v) \ ++ ({ \ ++ unsigned int __val = v; \ ++ asm("mcr p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \ ++ : \ ++ : "r" (__val) \ ++ : "cc"); \ ++ }) + #else + extern unsigned int processor_id; + #define read_cpuid(reg) (processor_id) + + +-- +Catalin + + diff --git a/packages/linux/linux-omap/mru-clocks1.diff b/packages/linux/linux-omap/mru-clocks1.diff new file mode 100644 index 0000000000..d7dadbc85e --- /dev/null +++ b/packages/linux/linux-omap/mru-clocks1.diff @@ -0,0 +1,25 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Tue, 22 Jul 2008 00:31:11 +0000 (+0100) +Subject: ARM: OMAP: make dpll4_m4_ck programmable with clk_set_rate() +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=2b7b958dc79e51127d7a4ecf88ce12dbc6c31426 + +ARM: OMAP: make dpll4_m4_ck programmable with clk_set_rate() + +Filling the set_rate and round_rate fields of dpll4_m4_ck makes +this clock programmable through clk_set_rate(). This is needed +to give omapfb control over the dss1_alwon_fck rate. +--- + +diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h +index 161da12..876eb13 100644 +--- a/arch/arm/mach-omap2/clock34xx.h ++++ b/arch/arm/mach-omap2/clock34xx.h +@@ -815,6 +815,8 @@ static struct clk dpll4_m4_ck = { + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | + PARENT_CONTROLS_CLOCK, + .recalc = &omap2_clksel_recalc, ++ .set_rate = &omap2_clksel_set_rate, ++ .round_rate = &omap2_clksel_round_rate, + }; + + /* The PWRDN bit is apparently only available on 3430ES2 and above */ diff --git a/packages/linux/linux-omap/mru-clocks2.diff b/packages/linux/linux-omap/mru-clocks2.diff new file mode 100644 index 0000000000..c8b370da03 --- /dev/null +++ b/packages/linux/linux-omap/mru-clocks2.diff @@ -0,0 +1,62 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Tue, 22 Jul 2008 00:58:18 +0000 (+0100) +Subject: ARM: OMAP: add clk_get_parent() for OMAP2/3 +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=e2de5e5578fbaa9b4b75074796da0608fc93e6ae + +ARM: OMAP: add clk_get_parent() for OMAP2/3 + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c +index 577be44..28aec36 100644 +--- a/arch/arm/mach-omap2/clock.c ++++ b/arch/arm/mach-omap2/clock.c +@@ -824,6 +824,11 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) + return 0; + } + ++struct clk *omap2_clk_get_parent(struct clk *clk) ++{ ++ return clk->parent; ++} ++ + /* DPLL rate rounding code */ + + /** +diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h +index 49245f7..4aa69d5 100644 +--- a/arch/arm/mach-omap2/clock.h ++++ b/arch/arm/mach-omap2/clock.h +@@ -29,6 +29,7 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate); + int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent); + int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance); + long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate); ++struct clk *omap2_clk_get_parent(struct clk *clk); + + #ifdef CONFIG_OMAP_RESET_CLOCKS + void omap2_clk_disable_unused(struct clk *clk); +diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c +index 54cc6e1..ed7af21 100644 +--- a/arch/arm/mach-omap2/clock24xx.c ++++ b/arch/arm/mach-omap2/clock24xx.c +@@ -422,6 +422,7 @@ static struct clk_functions omap2_clk_functions = { + .clk_round_rate = omap2_clk_round_rate, + .clk_set_rate = omap2_clk_set_rate, + .clk_set_parent = omap2_clk_set_parent, ++ .clk_get_parent = omap2_clk_get_parent, + .clk_disable_unused = omap2_clk_disable_unused, + #ifdef CONFIG_CPU_FREQ + .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table, +diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c +index 04dedec..08c8c46 100644 +--- a/arch/arm/mach-omap2/clock34xx.c ++++ b/arch/arm/mach-omap2/clock34xx.c +@@ -541,6 +541,7 @@ static struct clk_functions omap2_clk_functions = { + .clk_round_rate = omap2_clk_round_rate, + .clk_set_rate = omap2_clk_set_rate, + .clk_set_parent = omap2_clk_set_parent, ++ .clk_get_parent = omap2_clk_get_parent, + .clk_disable_unused = omap2_clk_disable_unused, + }; + diff --git a/packages/linux/linux-omap/mru-clocks3.diff b/packages/linux/linux-omap/mru-clocks3.diff new file mode 100644 index 0000000000..f8407fc2d5 --- /dev/null +++ b/packages/linux/linux-omap/mru-clocks3.diff @@ -0,0 +1,94 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 23 Jul 2008 08:40:07 +0000 (+0100) +Subject: ARM: OMAP: Set DSS1_ALWON_FCLK to a multiple of the pixel clock +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=01ee28c50701caa94739e764c3dae9298edd8216 + +ARM: OMAP: Set DSS1_ALWON_FCLK to a multiple of the pixel clock + +This sets the DSS1_ALWON_FCLK clock as close as possible to a +multiple of the requested pixel clock, while keeping it below +the 173MHz limit. + +Due to of the structure of the clock tree, dss1_alwon_fck cannot +be set directly, and we must use dpll4_m4_ck instead. + +Signed-off-by: Mans Rullgard <mans@mansr.com> +--- + +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index fd06ca2..e0e8528 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -176,6 +176,7 @@ static struct { + + struct clk *dss_ick, *dss1_fck; + struct clk *dss_54m_fck; ++ struct clk *dpll4_m4_ck; + + enum omapfb_update_mode update_mode; + struct omapfb_device *fbdev; +@@ -738,21 +739,34 @@ static void setup_color_conv_coef(void) + MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range); + } + +-#define MAX_FCK_LCD 173000000 ++#define MAX_FCK 173000000 + + static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div) + { ++ unsigned long prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ unsigned long pcd_min = is_tft? 2: 3; ++ unsigned long fck_div; + unsigned long fck, lck; + + pck = max(1, pck); ++ ++ if (pck * pcd_min > MAX_FCK) { ++ dev_warn(dispc.fbdev->dev, "pixclock %d kHz too high.\n", ++ pck / 1000); ++ pck = MAX_FCK / pcd_min; ++ } ++ ++ fck = pck * 2; ++ fck_div = (prate + pck) / fck; ++ if (fck_div > 16) ++ fck_div /= (fck_div + 15) / 16; ++ if (fck_div < 1) ++ fck_div = 1; ++ clk_set_rate(dispc.dpll4_m4_ck, prate / fck_div); + fck = clk_get_rate(dispc.dss1_fck); +- *lck_div = (fck + MAX_FCK_LCD - 1) / MAX_FCK_LCD; +- lck = fck / *lck_div; +- *pck_div = (lck + pck - 1) / pck; +- if (is_tft) +- *pck_div = max(2, *pck_div); +- else +- *pck_div = max(3, *pck_div); ++ ++ *lck_div = 1; ++ *pck_div = (fck + pck - 1) / pck; + if (*pck_div > 255) { + *pck_div = 255; + lck = pck * *pck_div; +@@ -914,11 +928,21 @@ static int get_dss_clocks(void) + return PTR_ERR(dispc.dss_54m_fck); + } + ++ if (IS_ERR((dispc.dpll4_m4_ck = ++ clk_get(dispc.fbdev->dev, "dpll4_m4_ck")))) { ++ dev_err(dispc.fbdev->dev, "can't get dpll4_m4_ck"); ++ clk_put(dispc.dss_ick); ++ clk_put(dispc.dss1_fck); ++ clk_put(dispc.dss_54m_fck); ++ return PTR_ERR(dispc.dss_54m_fck); ++ } ++ + return 0; + } + + static void put_dss_clocks(void) + { ++ clk_put(dispc.dpll4_m4_ck); + clk_put(dispc.dss_54m_fck); + clk_put(dispc.dss1_fck); + clk_put(dispc.dss_ick); diff --git a/packages/linux/linux-omap/musb-dmafix.patch b/packages/linux/linux-omap/musb-dmafix.patch new file mode 100644 index 0000000000..259b79be59 --- /dev/null +++ b/packages/linux/linux-omap/musb-dmafix.patch @@ -0,0 +1,275 @@ +From: Gadiyar, Anand <gadiyar@ti.com> +Date: Wed, 13 Aug 2008 07:05:29 +0000 (+0530) +Subject: MUSB: Workaround for simultaneous TX and RX usage +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=2e6aa4efb0e14c51ff0427927b1b38136911fa93 + +MUSB: Workaround for simultaneous TX and RX usage + +MUSB: Workaround for simultaneous TX and RX usage + +MUSB RTL V1.4 has a hardware issue which results in a DMA controller +hang when TX and RX DMA channels are simultaneously enabled. This +affects at least OMAP2430 and OMAP34XX. + +Since RX transfers are in Mode 0 and anyway result in one DMA interrupt +per packet, we can use System DMA to unload the RX fifos. MUSB DMA can +be used for all TX channels as before. + +Tested with full-duplex TX and RX transfers using g_ether. Runs for 24 +hours without a hang. Without this patch, the hang occurs within minutes. + +This issue was first reported by Jon Hunter on [1] + +[1] http://marc.info/?l=linux-omap&m=119634480534453&w=2 + +Signed-off-by: Anand Gadiyar <gadiyar@ti.com> +--- + +diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig +index a485a86..8583e54 100644 +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -150,6 +150,14 @@ config USB_INVENTRA_DMA + help + Enable DMA transfers using Mentor's engine. + ++config MUSB_USE_SYSTEM_DMA_RX ++ bool 'Use System DMA for RX endpoints' ++ depends on USB_MUSB_HDRC && USB_INVENTRA_DMA ++ help ++ MUSB RTL version 1.4 has a hardware issue when TX and RX DMA ++ channels are simultaneously enabled. To work around this issue, ++ you can choose to use System DMA for RX channels. ++ + config USB_TI_CPPI_DMA + bool + depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY +diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c +index 32bb1e2..d1c1ea0 100644 +--- a/drivers/usb/musb/musbhsdma.c ++++ b/drivers/usb/musb/musbhsdma.c +@@ -34,6 +34,7 @@ + #include <linux/interrupt.h> + #include <linux/platform_device.h> + #include "musb_core.h" ++#include <asm/dma.h> + + #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) + #include "omap2430.h" +@@ -64,6 +65,9 @@ + + #define MUSB_HSDMA_CHANNELS 8 + ++#define MUSB_FIFO_ADDRESS(epnum) \ ++ ((unsigned long) (OMAP_HSOTG_BASE + MUSB_FIFO_OFFSET(epnum))) ++ + struct musb_dma_controller; + + struct musb_dma_channel { +@@ -75,6 +79,8 @@ struct musb_dma_channel { + u8 bIndex; + u8 epnum; + u8 transmit; ++ ++ int sysdma_channel; + }; + + struct musb_dma_controller { +@@ -93,6 +99,42 @@ static int dma_controller_start(struct dma_controller *c) + return 0; + } + ++#ifdef CONFIG_MUSB_USE_SYSTEM_DMA_RX ++static void musb_sysdma_completion(int lch, u16 ch_status, void *data) ++{ ++ u32 dwAddress; ++ unsigned long flags; ++ ++ struct dma_channel *pChannel; ++ ++ struct musb_dma_channel *pImplChannel = ++ (struct musb_dma_channel *) data; ++ struct musb_dma_controller *controller = pImplChannel->controller; ++ struct musb *musb = controller->pDmaPrivate; ++ pChannel = &pImplChannel->Channel; ++ ++ DBG(2, "lch = 0x%d, ch_status = 0x%x\n", lch, ch_status); ++ spin_lock_irqsave(&musb->lock, flags); ++ ++ dwAddress = (u32) omap_get_dma_dst_pos(pImplChannel->sysdma_channel); ++ pChannel->actual_len = dwAddress - pImplChannel->dwStartAddress; ++ ++ DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", ++ pChannel, pImplChannel->dwStartAddress, dwAddress, ++ pChannel->actual_len, pImplChannel->len, ++ (pChannel->actual_len < pImplChannel->len) ? ++ "=> reconfig 0": "=> complete"); ++ ++ pChannel->status = MUSB_DMA_STATUS_FREE; ++ musb_dma_completion(musb, pImplChannel->epnum, pImplChannel->transmit); ++ ++ spin_unlock_irqrestore(&musb->lock, flags); ++ return; ++} ++#else ++#define musb_sysdma_completion NULL ++#endif ++ + static void dma_channel_release(struct dma_channel *pChannel); + + static int dma_controller_stop(struct dma_controller *c) +@@ -144,6 +186,29 @@ static struct dma_channel *dma_channel_allocate(struct dma_controller *c, + /* Tx => mode 1; Rx => mode 0 */ + pChannel->desired_mode = transmit; + pChannel->actual_len = 0; ++ pImplChannel->sysdma_channel = -1; ++ ++#ifdef CONFIG_MUSB_USE_SYSTEM_DMA_RX ++ if (!transmit) { ++ int ret; ++ ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, ++ "MUSB SysDMA", musb_sysdma_completion, ++ (void *) pImplChannel, ++ &(pImplChannel->sysdma_channel)); ++ ++ if (ret) { ++ printk(KERN_ERR "request_dma failed:" ++ " %d\n", ret); ++ controller->bmUsedChannels &= ++ ~(1 << bBit); ++ pChannel->status = ++ MUSB_DMA_STATUS_UNKNOWN; ++ pImplChannel->sysdma_channel = -1; ++ pChannel = NULL; ++ } ++ } ++#endif ++ + break; + } + } +@@ -163,6 +228,12 @@ static void dma_channel_release(struct dma_channel *pChannel) + ~(1 << pImplChannel->bIndex); + + pChannel->status = MUSB_DMA_STATUS_UNKNOWN; ++ ++ if (pImplChannel->sysdma_channel != -1) { ++ omap_stop_dma(pImplChannel->sysdma_channel); ++ omap_free_dma(pImplChannel->sysdma_channel); ++ pImplChannel->sysdma_channel = -1; ++ } + } + + static void configure_channel(struct dma_channel *pChannel, +@@ -179,41 +250,69 @@ static void configure_channel(struct dma_channel *pChannel, + DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n", + pChannel, packet_sz, dma_addr, len, mode); + +- if (mode) { +- csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; +- BUG_ON(len < packet_sz); ++ if (pImplChannel->sysdma_channel != -1) { ++ /* System DMA */ ++ /* RX: set src = FIFO */ ++ ++ omap_set_dma_transfer_params(pImplChannel->sysdma_channel, ++ OMAP_DMA_DATA_TYPE_S8, ++ len, 1, /* One frame */ ++ OMAP_DMA_SYNC_ELEMENT, ++ OMAP24XX_DMA_NO_DEVICE, ++ 0); /* Src Sync */ ++ ++ omap_set_dma_src_params(pImplChannel->sysdma_channel, 0, ++ OMAP_DMA_AMODE_CONSTANT, ++ MUSB_FIFO_ADDRESS(pImplChannel->epnum), ++ 0, 0); + +- if (packet_sz >= 64) { +- csr |= MUSB_HSDMA_BURSTMODE_INCR16 ++ omap_set_dma_dest_params(pImplChannel->sysdma_channel, 0, ++ OMAP_DMA_AMODE_POST_INC, dma_addr, ++ 0, 0); ++ ++ omap_set_dma_dest_data_pack(pImplChannel->sysdma_channel, 1); ++ omap_set_dma_dest_burst_mode(pImplChannel->sysdma_channel, ++ OMAP_DMA_DATA_BURST_16); ++ ++ omap_start_dma(pImplChannel->sysdma_channel); ++ ++ } else { /* Mentor DMA */ ++ if (mode) { ++ csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; ++ BUG_ON(len < packet_sz); ++ ++ if (packet_sz >= 64) { ++ csr |= MUSB_HSDMA_BURSTMODE_INCR16 + << MUSB_HSDMA_BURSTMODE_SHIFT; +- } else if (packet_sz >= 32) { +- csr |= MUSB_HSDMA_BURSTMODE_INCR8 ++ } else if (packet_sz >= 32) { ++ csr |= MUSB_HSDMA_BURSTMODE_INCR8 + << MUSB_HSDMA_BURSTMODE_SHIFT; +- } else if (packet_sz >= 16) { +- csr |= MUSB_HSDMA_BURSTMODE_INCR4 ++ } else if (packet_sz >= 16) { ++ csr |= MUSB_HSDMA_BURSTMODE_INCR4 + << MUSB_HSDMA_BURSTMODE_SHIFT; ++ } + } +- } + +- csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) +- | (1 << MUSB_HSDMA_ENABLE_SHIFT) +- | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) +- | (pImplChannel->transmit +- ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) +- : 0); +- +- /* address/count */ +- musb_writel(mbase, +- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), +- dma_addr); +- musb_writel(mbase, +- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), +- len); +- +- /* control (this should start things) */ +- musb_writew(mbase, +- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), +- csr); ++ csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) ++ | (1 << MUSB_HSDMA_ENABLE_SHIFT) ++ | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) ++ | (pImplChannel->transmit ++ ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) ++ : 0); ++ ++ /* address/count */ ++ musb_writel(mbase, ++ MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), ++ dma_addr); ++ musb_writel(mbase, ++ MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), ++ len); ++ ++ /* control (this should start things) */ ++ musb_writew(mbase, ++ MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), ++ csr); ++ } /* Mentor DMA */ + } + + static int dma_channel_program(struct dma_channel *pChannel, +@@ -265,6 +364,12 @@ static int dma_channel_abort(struct dma_channel *pChannel) + MUSB_EP_OFFSET(pImplChannel->epnum, MUSB_TXCSR), + csr); + } else { ++ if (pImplChannel->sysdma_channel != -1) { ++ omap_stop_dma(pImplChannel->sysdma_channel); ++ omap_free_dma(pImplChannel->sysdma_channel); ++ pImplChannel->sysdma_channel = -1; ++ } ++ + csr = musb_readw(mbase, + MUSB_EP_OFFSET(pImplChannel->epnum, MUSB_RXCSR)); + csr &= ~(MUSB_RXCSR_AUTOCLEAR | diff --git a/packages/linux/linux-omap/no-cortex-deadlock.patch b/packages/linux/linux-omap/no-cortex-deadlock.patch new file mode 100644 index 0000000000..5bb6d22484 --- /dev/null +++ b/packages/linux/linux-omap/no-cortex-deadlock.patch @@ -0,0 +1,75 @@ +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 30 Jul 2008 08:25:51 +0000 (+0100) +Subject: ARM: NEON L1 cache bug workaround (erratum 451034) +X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=26023493baf13e0a67fd6cf08d87be5ff6f7c56d + +ARM: NEON L1 cache bug workaround (erratum 451034) + +On Cortex-A8 r1p0 and r1p1, executing a NEON store with an integer +store in the store buffer, can cause a processor deadlock under +certain conditions. + +Executing a DMB instruction before saving NEON/VFP registers and before +return to userspace makes it safe to run code which includes similar +counter-measures. Userspace code can still trigger the deadlock, so +a different workaround is required to safely run untrusted code. + +See ARM Cortex-A8 Errata Notice (PR120-PRDC-008070) for full details. +--- + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 8c75840..1172e14 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1071,6 +1071,22 @@ config NEON + Say Y to include support code for NEON, the ARMv7 Advanced SIMD + Extension. + ++config NEON_CACHE_BUG ++ bool "NEON L1 cache bug workaround (erratum 451034)" ++ depends on VFPv3 ++ help ++ On Cortex-A8 r1p0 and r1p1, executing a NEON store with an integer ++ store in the store buffer, can cause a processor deadlock under ++ certain conditions. ++ ++ See ARM Cortex-A8 Errata Notice (PR120-PRDC-008070) for full details. ++ ++ Say Y to include a workaround. ++ ++ WARNING: Even with this option enabled, userspace code can trigger ++ the deadlock. To safely run untrusted code, a different fix is ++ required. ++ + endmenu + + menu "Userspace binary formats" +diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S +index 597ed00..e50094e 100644 +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -68,6 +68,10 @@ no_work_pending: + /* perform architecture specific actions before user return */ + arch_ret_to_user r1, lr + ++#ifdef CONFIG_NEON_CACHE_BUG ++ dmb ++#endif ++ + @ slow_restore_user_regs + ldr r1, [sp, #S_PSR] @ get calling cpsr + ldr lr, [sp, #S_PC]! @ get pc +diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h +index cccb389..c9d2976 100644 +--- a/arch/arm/include/asm/vfpmacros.h ++++ b/arch/arm/include/asm/vfpmacros.h +@@ -32,6 +32,9 @@ + + @ write all the working registers out of the VFP + .macro VFPFSTMIA, base, tmp ++#ifdef CONFIG_NEON_CACHE_BUG ++ dmb ++#endif + #if __LINUX_ARM_ARCH__ < 6 + STC p11, cr0, [\base],#33*4 @ FSTMIAX \base!, {d0-d15} + #else diff --git a/packages/linux/linux-omap/no-empty-flash-warnings.patch b/packages/linux/linux-omap/no-empty-flash-warnings.patch new file mode 100644 index 0000000000..ab344b0449 --- /dev/null +++ b/packages/linux/linux-omap/no-empty-flash-warnings.patch @@ -0,0 +1,15 @@ +diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c +index 1d437de..33b3feb 100644 +--- a/fs/jffs2/scan.c ++++ b/fs/jffs2/scan.c +@@ -647,8 +647,8 @@ scan_more: + inbuf_ofs = ofs - buf_ofs; + while (inbuf_ofs < scan_end) { + if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) { +- printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", +- empty_start, ofs); ++// printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", ++// empty_start, ofs); + if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start))) + return err; + goto scan_more; diff --git a/packages/linux/linux-omap/no-harry-potter.diff b/packages/linux/linux-omap/no-harry-potter.diff new file mode 100644 index 0000000000..2bb20ab9c0 --- /dev/null +++ b/packages/linux/linux-omap/no-harry-potter.diff @@ -0,0 +1,11 @@ +--- /tmp/Makefile 2008-04-24 14:36:20.509598016 +0200 ++++ git/arch/arm/Makefile 2008-04-24 14:36:31.949546584 +0200 +@@ -47,7 +47,7 @@ + # Note that GCC does not numerically define an architecture version + # macro, but instead defines a whole series of macros which makes + # testing for a specific architecture or later rather impossible. +-arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a) ++arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) + arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) + # Only override the compiler option if ARMv6. The ARMv6K extensions are + # always available in ARMv7 diff --git a/packages/linux/linux-omap/omap-2430-lcd.patch b/packages/linux/linux-omap/omap-2430-lcd.patch new file mode 100644 index 0000000000..8f8a687c06 --- /dev/null +++ b/packages/linux/linux-omap/omap-2430-lcd.patch @@ -0,0 +1,11 @@ +--- git/drivers/video/omap/lcd_2430sdp.c.orig 2007-08-13 14:35:17.000000000 -0700 ++++ git/drivers/video/omap/lcd_2430sdp.c 2007-08-13 14:35:55.000000000 -0700 +@@ -32,7 +32,7 @@ + #define LCD_PANEL_BACKLIGHT_GPIO 91 + #define LCD_PANEL_ENABLE_GPIO 154 + #define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */ +-#define PM_RECEIVER TWL4030_MODULE_PM_RECIEVER ++#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER + #define ENABLE_VAUX2_DEDICATED 0x09 + #define ENABLE_VAUX2_DEV_GRP 0x20 + diff --git a/packages/linux/linux-omap/omap1710h3/.mtn2git_empty b/packages/linux/linux-omap/omap1710h3/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-omap/omap1710h3/.mtn2git_empty diff --git a/packages/linux/linux-omap/omap2420h4/.mtn2git_empty b/packages/linux/linux-omap/omap2420h4/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-omap/omap2420h4/.mtn2git_empty diff --git a/packages/linux/linux-omap/omap2430sdp/.mtn2git_empty b/packages/linux/linux-omap/omap2430sdp/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-omap/omap2430sdp/.mtn2git_empty diff --git a/packages/linux/linux-omap/omap3evm/.mtn2git_empty b/packages/linux/linux-omap/omap3evm/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-omap/omap3evm/.mtn2git_empty diff --git a/packages/linux/linux-omap/omap5912osk/.mtn2git_empty b/packages/linux/linux-omap/omap5912osk/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-omap/omap5912osk/.mtn2git_empty diff --git a/packages/linux/linux-omap/oprofile-0.9.3.armv7.diff b/packages/linux/linux-omap/oprofile-0.9.3.armv7.diff new file mode 100644 index 0000000000..02dc079095 --- /dev/null +++ b/packages/linux/linux-omap/oprofile-0.9.3.armv7.diff @@ -0,0 +1,612 @@ +Hi, + +This patch adds Oprofile support on ARMv7, using the PMNC unit. +Tested on OMAP3430 SDP. + +Feedback and comments are welcome. + +The patch to user space components is attached for reference. It i applies +against version 0.9.3 of oprofile source +(http://prdownloads.sourceforge.net/oprofile/oprofile-0.9.3.tar.gz). + +Regards, +Jean. + +--- + +From: Jean Pihet <jpihet@mvista.com> +Date: Tue, 6 May 2008 17:21:44 +0200 +Subject: [PATCH] ARM: Add ARMv7 oprofile support + +Add ARMv7 Oprofile support to kernel + +Signed-off-by: Jean Pihet <jpihet@mvista.com> +--- + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index c60a27d..60b50a0 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -161,6 +161,11 @@ config OPROFILE_MPCORE + config OPROFILE_ARM11_CORE + bool + ++config OPROFILE_ARMV7 ++ def_bool y ++ depends on CPU_V7 && !SMP ++ bool ++ + endif + + config VECTORS_BASE +diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile +index e61d0cc..88e31f5 100644 +--- a/arch/arm/oprofile/Makefile ++++ b/arch/arm/oprofile/Makefile +@@ -11,3 +11,4 @@ oprofile-$(CONFIG_CPU_XSCALE) += op_model_xscale.o + oprofile-$(CONFIG_OPROFILE_ARM11_CORE) += op_model_arm11_core.o + oprofile-$(CONFIG_OPROFILE_ARMV6) += op_model_v6.o + oprofile-$(CONFIG_OPROFILE_MPCORE) += op_model_mpcore.o ++oprofile-$(CONFIG_OPROFILE_ARMV7) += op_model_v7.o +diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c +index 0a5cf3a..3fcd752 100644 +--- a/arch/arm/oprofile/common.c ++++ b/arch/arm/oprofile/common.c +@@ -145,6 +145,10 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) + spec = &op_mpcore_spec; + #endif + ++#ifdef CONFIG_OPROFILE_ARMV7 ++ spec = &op_armv7_spec; ++#endif ++ + if (spec) { + ret = spec->init(); + if (ret < 0) +diff --git a/arch/arm/oprofile/op_arm_model.h +b/arch/arm/oprofile/op_arm_model.h +index 4899c62..8c4e4f6 100644 +--- a/arch/arm/oprofile/op_arm_model.h ++++ b/arch/arm/oprofile/op_arm_model.h +@@ -26,6 +26,7 @@ extern struct op_arm_model_spec op_xscale_spec; + + extern struct op_arm_model_spec op_armv6_spec; + extern struct op_arm_model_spec op_mpcore_spec; ++extern struct op_arm_model_spec op_armv7_spec; + + extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth); + +diff --git a/arch/arm/oprofile/op_model_v7.c b/arch/arm/oprofile/op_model_v7.c +new file mode 100644 +index 0000000..a159bc1 +--- /dev/null ++++ b/arch/arm/oprofile/op_model_v7.c +@@ -0,0 +1,407 @@ ++/** ++ * @file op_model_v7.c ++ * ARM V7 (Cortex A8) Event Monitor Driver ++ * ++ * @remark Copyright 2008 Jean Pihet <jpihet@mvista.com> ++ * @remark Copyright 2004 ARM SMP Development Team ++ */ ++#include <linux/types.h> ++#include <linux/errno.h> ++#include <linux/oprofile.h> ++#include <linux/interrupt.h> ++#include <linux/irq.h> ++#include <linux/smp.h> ++ ++#include "op_counter.h" ++#include "op_arm_model.h" ++#include "op_model_v7.h" ++ ++/* #define DEBUG */ ++ ++ ++/* ++ * ARM V7 PMNC support ++ */ ++ ++static u32 cnt_en[CNTMAX]; ++ ++static inline void armv7_pmnc_write(u32 val) ++{ ++ val &= PMNC_MASK; ++ asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (val)); ++} ++ ++static inline u32 armv7_pmnc_read(void) ++{ ++ u32 val; ++ ++ asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); ++ return val; ++} ++ ++static inline u32 armv7_pmnc_enable_counter(unsigned int cnt) ++{ ++ u32 val; ++ ++ if (cnt >= CNTMAX) { ++ printk(KERN_ERR "oprofile: CPU%u enabling wrong PMNC counter" ++ " %d\n", smp_processor_id(), cnt); ++ return -1; ++ } ++ ++ if (cnt == CCNT) ++ val = CNTENS_C; ++ else ++ val = (1 << (cnt - CNT0)); ++ ++ val &= CNTENS_MASK; ++ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); ++ ++ return cnt; ++} ++ ++static inline u32 armv7_pmnc_disable_counter(unsigned int cnt) ++{ ++ u32 val; ++ ++ if (cnt >= CNTMAX) { ++ printk(KERN_ERR "oprofile: CPU%u disabling wrong PMNC counter" ++ " %d\n", smp_processor_id(), cnt); ++ return -1; ++ } ++ ++ if (cnt == CCNT) ++ val = CNTENC_C; ++ else ++ val = (1 << (cnt - CNT0)); ++ ++ val &= CNTENC_MASK; ++ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); ++ ++ return cnt; ++} ++ ++static inline u32 armv7_pmnc_enable_intens(unsigned int cnt) ++{ ++ u32 val; ++ ++ if (cnt >= CNTMAX) { ++ printk(KERN_ERR "oprofile: CPU%u enabling wrong PMNC counter" ++ " interrupt enable %d\n", smp_processor_id(), cnt); ++ return -1; ++ } ++ ++ if (cnt == CCNT) ++ val = INTENS_C; ++ else ++ val = (1 << (cnt - CNT0)); ++ ++ val &= INTENS_MASK; ++ asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val)); ++ ++ return cnt; ++} ++ ++static inline u32 armv7_pmnc_getreset_flags(void) ++{ ++ u32 val; ++ ++ /* Read */ ++ asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); ++ ++ /* Write to clear flags */ ++ val &= FLAG_MASK; ++ asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val)); ++ ++ return val; ++} ++ ++static inline int armv7_pmnc_select_counter(unsigned int cnt) ++{ ++ u32 val; ++ ++ if ((cnt == CCNT) || (cnt >= CNTMAX)) { ++ printk(KERN_ERR "oprofile: CPU%u selecting wrong PMNC counteri" ++ " %d\n", smp_processor_id(), cnt); ++ return -1; ++ } ++ ++ val = (cnt - CNT0) & SELECT_MASK; ++ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); ++ ++ return cnt; ++} ++ ++static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val) ++{ ++ if (armv7_pmnc_select_counter(cnt) == cnt) { ++ val &= EVTSEL_MASK; ++ asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); ++ } ++} ++ ++static void armv7_pmnc_reset_counter(unsigned int cnt) ++{ ++ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt); ++ u32 val = -(u32)counter_config[cpu_cnt].count; ++ ++ switch (cnt) { ++ case CCNT: ++ armv7_pmnc_disable_counter(cnt); ++ ++ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (val)); ++ ++ if (cnt_en[cnt] != 0) ++ armv7_pmnc_enable_counter(cnt); ++ ++ break; ++ ++ case CNT0: ++ case CNT1: ++ case CNT2: ++ case CNT3: ++ armv7_pmnc_disable_counter(cnt); ++ ++ if (armv7_pmnc_select_counter(cnt) == cnt) ++ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val)); ++ ++ if (cnt_en[cnt] != 0) ++ armv7_pmnc_enable_counter(cnt); ++ ++ break; ++ ++ default: ++ printk(KERN_ERR "oprofile: CPU%u resetting wrong PMNC counter" ++ " %d\n", smp_processor_id(), cnt); ++ break; ++ } ++} ++ ++int armv7_setup_pmnc(void) ++{ ++ unsigned int cnt; ++ ++ if (armv7_pmnc_read() & PMNC_E) { ++ printk(KERN_ERR "oprofile: CPU%u PMNC still enabled when setup" ++ " new event counter.\n", smp_processor_id()); ++ return -EBUSY; ++ } ++ ++ /* ++ * Initialize & Reset PMNC: C bit, D bit and P bit. ++ * Note: Using a slower count for CCNT (D bit: divide by 64) results ++ * in a more stable system ++ */ ++ armv7_pmnc_write(PMNC_P | PMNC_C | PMNC_D); ++ ++ ++ for (cnt = CCNT; cnt < CNTMAX; cnt++) { ++ unsigned long event; ++ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt); ++ ++ /* ++ * Disable counter ++ */ ++ armv7_pmnc_disable_counter(cnt); ++ cnt_en[cnt] = 0; ++ ++ if (!counter_config[cpu_cnt].enabled) ++ continue; ++ ++ event = counter_config[cpu_cnt].event & 255; ++ ++ /* ++ * Set event (if destined for PMNx counters) ++ * We don't need to set the event if it's a cycle count ++ */ ++ if (cnt != CCNT) ++ armv7_pmnc_write_evtsel(cnt, event); ++ ++ /* ++ * Enable interrupt for this counter ++ */ ++ armv7_pmnc_enable_intens(cnt); ++ ++ /* ++ * Reset counter ++ */ ++ armv7_pmnc_reset_counter(cnt); ++ ++ /* ++ * Enable counter ++ */ ++ armv7_pmnc_enable_counter(cnt); ++ cnt_en[cnt] = 1; ++ } ++ ++ return 0; ++} ++ ++static inline void armv7_start_pmnc(void) ++{ ++ armv7_pmnc_write(armv7_pmnc_read() | PMNC_E); ++} ++ ++static inline void armv7_stop_pmnc(void) ++{ ++ armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E); ++} ++ ++/* ++ * CPU counters' IRQ handler (one IRQ per CPU) ++ */ ++static irqreturn_t armv7_pmnc_interrupt(int irq, void *arg) ++{ ++ struct pt_regs *regs = get_irq_regs(); ++ unsigned int cnt; ++ u32 flags; ++ ++ ++ /* ++ * Stop IRQ generation ++ */ ++ armv7_stop_pmnc(); ++ ++ /* ++ * Get and reset overflow status flags ++ */ ++ flags = armv7_pmnc_getreset_flags(); ++ ++ /* ++ * Cycle counter ++ */ ++ if (flags & FLAG_C) { ++ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), CCNT); ++ armv7_pmnc_reset_counter(CCNT); ++ oprofile_add_sample(regs, cpu_cnt); ++ } ++ ++ /* ++ * PMNC counters 0:3 ++ */ ++ for (cnt = CNT0; cnt < CNTMAX; cnt++) { ++ if (flags & (1 << (cnt - CNT0))) { ++ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt); ++ armv7_pmnc_reset_counter(cnt); ++ oprofile_add_sample(regs, cpu_cnt); ++ } ++ } ++ ++ /* ++ * Allow IRQ generation ++ */ ++ armv7_start_pmnc(); ++ ++ return IRQ_HANDLED; ++} ++ ++int armv7_request_interrupts(int *irqs, int nr) ++{ ++ unsigned int i; ++ int ret = 0; ++ ++ for (i = 0; i < nr; i++) { ++ ret = request_irq(irqs[i], armv7_pmnc_interrupt, ++ IRQF_DISABLED, "CP15 PMNC", NULL); ++ if (ret != 0) { ++ printk(KERN_ERR "oprofile: unable to request IRQ%u" ++ " for ARMv7\n", ++ irqs[i]); ++ break; ++ } ++ } ++ ++ if (i != nr) ++ while (i-- != 0) ++ free_irq(irqs[i], NULL); ++ ++ return ret; ++} ++ ++void armv7_release_interrupts(int *irqs, int nr) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < nr; i++) ++ free_irq(irqs[i], NULL); ++} ++ ++#ifdef DEBUG ++static void armv7_pmnc_dump_regs(void) ++{ ++ u32 val; ++ unsigned int cnt; ++ ++ printk(KERN_INFO "PMNC registers dump:\n"); ++ ++ asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); ++ printk(KERN_INFO "PMNC =0x%08x\n", val); ++ ++ asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val)); ++ printk(KERN_INFO "CNTENS=0x%08x\n", val); ++ ++ asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val)); ++ printk(KERN_INFO "INTENS=0x%08x\n", val); ++ ++ asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); ++ printk(KERN_INFO "FLAGS =0x%08x\n", val); ++ ++ asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val)); ++ printk(KERN_INFO "SELECT=0x%08x\n", val); ++ ++ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); ++ printk(KERN_INFO "CCNT =0x%08x\n", val); ++ ++ for (cnt = CNT0; cnt < CNTMAX; cnt++) { ++ armv7_pmnc_select_counter(cnt); ++ asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); ++ printk(KERN_INFO "CNT[%d] count =0x%08x\n", cnt-CNT0, val); ++ asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val)); ++ printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n", cnt-CNT0, val); ++ } ++} ++#endif ++ ++ ++static int irqs[] = { ++#ifdef CONFIG_ARCH_OMAP3 ++ INT_34XX_BENCH_MPU_EMUL, ++#endif ++}; ++ ++static void armv7_pmnc_stop(void) ++{ ++#ifdef DEBUG ++ armv7_pmnc_dump_regs(); ++#endif ++ armv7_stop_pmnc(); ++ armv7_release_interrupts(irqs, ARRAY_SIZE(irqs)); ++} ++ ++static int armv7_pmnc_start(void) ++{ ++ int ret; ++ ++#ifdef DEBUG ++ armv7_pmnc_dump_regs(); ++#endif ++ ret = armv7_request_interrupts(irqs, ARRAY_SIZE(irqs)); ++ if (ret >= 0) ++ armv7_start_pmnc(); ++ ++ return ret; ++} ++ ++static int armv7_detect_pmnc(void) ++{ ++ return 0; ++} ++ ++struct op_arm_model_spec op_armv7_spec = { ++ .init = armv7_detect_pmnc, ++ .num_counters = 5, ++ .setup_ctrs = armv7_setup_pmnc, ++ .start = armv7_pmnc_start, ++ .stop = armv7_pmnc_stop, ++ .name = "arm/armv7", ++}; +diff --git a/arch/arm/oprofile/op_model_v7.h b/arch/arm/oprofile/op_model_v7.h +new file mode 100644 +index 0000000..08f40ea +--- /dev/null ++++ b/arch/arm/oprofile/op_model_v7.h +@@ -0,0 +1,101 @@ ++/** ++ * @file op_model_v7.h ++ * ARM v7 (Cortex A8) Event Monitor Driver ++ * ++ * @remark Copyright 2008 Jean Pihet <jpihet@mvista.com> ++ * @remark Copyright 2004 ARM SMP Development Team ++ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com> ++ * @remark Copyright 2000-2004 MontaVista Software Inc ++ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com> ++ * @remark Copyright 2004 Intel Corporation ++ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk> ++ * @remark Copyright 2004 Oprofile Authors ++ * ++ * @remark Read the file COPYING ++ * ++ * @author Zwane Mwaikambo ++ */ ++#ifndef OP_MODEL_V7_H ++#define OP_MODEL_V7_H ++ ++/* ++ * Per-CPU PMNC: config reg ++ */ ++#define PMNC_E (1 << 0) /* Enable all counters */ ++#define PMNC_P (1 << 1) /* Reset all counters */ ++#define PMNC_C (1 << 2) /* Cycle counter reset */ ++#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */ ++#define PMNC_X (1 << 4) /* Export to ETM */ ++#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ ++#define PMNC_MASK 0x3f /* Mask for writable bits */ ++ ++/* ++ * Available counters ++ */ ++#define CCNT 0 ++#define CNT0 1 ++#define CNT1 2 ++#define CNT2 3 ++#define CNT3 4 ++#define CNTMAX 5 ++ ++#define CPU_COUNTER(cpu, counter) ((cpu) * CNTMAX + (counter)) ++ ++/* ++ * CNTENS: counters enable reg ++ */ ++#define CNTENS_P0 (1 << 0) ++#define CNTENS_P1 (1 << 1) ++#define CNTENS_P2 (1 << 2) ++#define CNTENS_P3 (1 << 3) ++#define CNTENS_C (1 << 31) ++#define CNTENS_MASK 0x8000000f /* Mask for writable bits */ ++ ++/* ++ * CNTENC: counters disable reg ++ */ ++#define CNTENC_P0 (1 << 0) ++#define CNTENC_P1 (1 << 1) ++#define CNTENC_P2 (1 << 2) ++#define CNTENC_P3 (1 << 3) ++#define CNTENC_C (1 << 31) ++#define CNTENC_MASK 0x8000000f /* Mask for writable bits */ ++ ++/* ++ * INTENS: counters overflow interrupt enable reg ++ */ ++#define INTENS_P0 (1 << 0) ++#define INTENS_P1 (1 << 1) ++#define INTENS_P2 (1 << 2) ++#define INTENS_P3 (1 << 3) ++#define INTENS_C (1 << 31) ++#define INTENS_MASK 0x8000000f /* Mask for writable bits */ ++ ++/* ++ * EVTSEL: Event selection reg ++ */ ++#define EVTSEL_MASK 0x7f /* Mask for writable bits */ ++ ++/* ++ * SELECT: Counter selection reg ++ */ ++#define SELECT_MASK 0x1f /* Mask for writable bits */ ++ ++/* ++ * FLAG: counters overflow flag status reg ++ */ ++#define FLAG_P0 (1 << 0) ++#define FLAG_P1 (1 << 1) ++#define FLAG_P2 (1 << 2) ++#define FLAG_P3 (1 << 3) ++#define FLAG_C (1 << 31) ++#define FLAG_MASK 0x8000000f /* Mask for writable bits */ ++ ++ ++int armv7_setup_pmu(void); ++int armv7_start_pmu(void); ++int armv7_stop_pmu(void); ++int armv7_request_interrupts(int *, int); ++void armv7_release_interrupts(int *, int); ++ ++#endif + +diff --git a/arch/arm/plat-omap/include/mach/irqs.h +b/arch/arm/plat-omap/include/mach/irqs.h +index c80e160..89ca90e 100644 +--- a/arch/arm/plat-omap/include/mach/irqs.h ++++ b/arch/arm/plat-omap/include/mach/irqs.h +@@ -297,6 +297,7 @@ + #define INT_243X_HS_USB_DMA 93 + #define INT_243X_CARKIT_IRQ 94 + ++#define INT_34XX_BENCH_MPU_EMUL 3 + #define INT_34XX_ST_MCBSP2_IRQ 4 + #define INT_34XX_ST_MCBSP3_IRQ 5 + #define INT_34XX_SYS_NIRQ 7 diff --git a/packages/linux/linux-omap/read_die_ids.patch b/packages/linux/linux-omap/read_die_ids.patch new file mode 100644 index 0000000000..3f6c930cc1 --- /dev/null +++ b/packages/linux/linux-omap/read_die_ids.patch @@ -0,0 +1,23 @@ +OMAP2/3 TAP: enable debug messages + +From: Paul Walmsley <paul@pwsan.com> + +This patch causes the OMAP2/3 chip ID code to display the full DIE_ID registers at boot. + +--- + + arch/arm/mach-omap2/id.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c +index c7f9ab7..a154b5e 100644 +--- a/arch/arm/mach-omap2/id.c ++++ b/arch/arm/mach-omap2/id.c +@@ -10,6 +10,7 @@ + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ ++#define DEBUG + + #include <linux/module.h> + #include <linux/kernel.h> diff --git a/packages/linux/linux-omap/soc.patch b/packages/linux/linux-omap/soc.patch new file mode 100644 index 0000000000..f4cce21ca7 --- /dev/null +++ b/packages/linux/linux-omap/soc.patch @@ -0,0 +1,1154 @@ +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 3903ab7..468536d 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -44,3 +44,7 @@ config SND_SOC_CS4270_VD33_ERRATA + config SND_SOC_TLV320AIC3X + tristate + depends on SND_SOC && I2C ++ ++config SND_SOC_TWL4030 ++ tristate ++ depends on SND_SOC && I2C +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 4e1314c..d2c0b12 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -6,6 +6,7 @@ snd-soc-wm9712-objs := wm9712.o + snd-soc-wm9713-objs := wm9713.o + snd-soc-cs4270-objs := cs4270.o + snd-soc-tlv320aic3x-objs := tlv320aic3x.o ++snd-soc-twl4030-objs := twl4030.o + + obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o + obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o +@@ -15,3 +16,4 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o + obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o + obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o + obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o ++obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o +diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c +new file mode 100644 +index 0000000..eb8370c +--- /dev/null ++++ b/sound/soc/codecs/twl4030.c +@@ -0,0 +1,625 @@ ++/* ++ * ALSA SoC TWL4030 codec driver ++ * ++ * Author: Steve Sakoman, <steve@sakoman.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/pm.h> ++#include <linux/i2c.h> ++#include <linux/platform_device.h> ++#include <linux/i2c/twl4030.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++#include <sound/initval.h> ++ ++#include "twl4030.h" ++ ++/* ++ * twl4030 register cache & default register settings ++ */ ++static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { ++ 0x00, // this register not used ++ 0x93, // REG_CODEC_MODE (0x1) ++ 0xc3, // REG_OPTION (0x2) ++ 0x00, // REG_UNKNOWN (0x3) ++ 0x00, // REG_MICBIAS_CTL (0x4) ++ 0x34, // REG_ANAMICL (0x5) ++ 0x14, // REG_ANAMICR (0x6) ++ 0x0a, // REG_AVADC_CTL (0x7) ++ 0x00, // REG_ADCMICSEL (0x8) ++ 0x00, // REG_DIGMIXING (0x9) ++ 0x0c, // REG_ATXL1PGA (0xA) ++ 0x0c, // REG_ATXR1PGA (0xB) ++ 0x00, // REG_AVTXL2PGA (0xC) ++ 0x00, // REG_AVTXR2PGA (0xD) ++ 0x01, // REG_AUDIO_IF (0xE) ++ 0x00, // REG_VOICE_IF (0xF) ++ 0x00, // REG_ARXR1PGA (0x10) ++ 0x00, // REG_ARXL1PGA (0x11) ++ 0x6c, // REG_ARXR2PGA (0x12) ++ 0x6c, // REG_ARXL2PGA (0x13) ++ 0x00, // REG_VRXPGA (0x14) ++ 0x00, // REG_VSTPGA (0x15) ++ 0x00, // REG_VRX2ARXPGA (0x16) ++ 0x0c, // REG_AVDAC_CTL (0x17) ++ 0x00, // REG_ARX2VTXPGA (0x18) ++ 0x00, // REG_ARXL1_APGA_CTL (0x19) ++ 0x00, // REG_ARXR1_APGA_CTL (0x1A) ++ 0x4b, // REG_ARXL2_APGA_CTL (0x1B) ++ 0x4b, // REG_ARXR2_APGA_CTL (0x1C) ++ 0x00, // REG_ATX2ARXPGA (0x1D) ++ 0x00, // REG_BT_IF (0x1E) ++ 0x00, // REG_BTPGA (0x1F) ++ 0x00, // REG_BTSTPGA (0x20) ++ 0x00, // REG_EAR_CTL (0x21) ++ 0x24, // REG_HS_SEL (0x22) ++ 0x0a, // REG_HS_GAIN_SET (0x23) ++ 0x00, // REG_HS_POPN_SET (0x24) ++ 0x00, // REG_PREDL_CTL (0x25) ++ 0x00, // REG_PREDR_CTL (0x26) ++ 0x00, // REG_PRECKL_CTL (0x27) ++ 0x00, // REG_PRECKR_CTL (0x28) ++ 0x00, // REG_HFL_CTL (0x29) ++ 0x00, // REG_HFR_CTL (0x2A) ++ 0x00, // REG_ALC_CTL (0x2B) ++ 0x00, // REG_ALC_SET1 (0x2C) ++ 0x00, // REG_ALC_SET2 (0x2D) ++ 0x00, // REG_BOOST_CTL (0x2E) ++ 0x01, // REG_SOFTVOL_CTL (0x2F) ++ 0x00, // REG_DTMF_FREQSEL (0x30) ++ 0x00, // REG_DTMF_TONEXT1H (0x31) ++ 0x00, // REG_DTMF_TONEXT1L (0x32) ++ 0x00, // REG_DTMF_TONEXT2H (0x33) ++ 0x00, // REG_DTMF_TONEXT2L (0x34) ++ 0x00, // REG_DTMF_TONOFF (0x35) ++ 0x00, // REG_DTMF_WANONOFF (0x36) ++ 0x00, // REG_I2S_RX_SCRAMBLE_H (0x37) ++ 0x00, // REG_I2S_RX_SCRAMBLE_M (0x38) ++ 0x00, // REG_I2S_RX_SCRAMBLE_L (0x39) ++ 0x16, // REG_APLL_CTL (0x3A) ++ 0x00, // REG_DTMF_CTL (0x3B) ++ 0x00, // REG_DTMF_PGA_CTL2 (0x3C) ++ 0x00, // REG_DTMF_PGA_CTL1 (0x3D) ++ 0x00, // REG_MISC_SET_1 (0x3E) ++ 0x00, // REG_PCMBTMUX (0x3F) ++ 0x00, // REG_RX_PATH_SEL (0x43) ++ 0x00, // REG_VDL_APGA_CTL (0x44) ++ 0x00, // REG_VIBRA_CTL (0x45) ++ 0x00, // REG_VIBRA_SET (0x46) ++ 0x00, // REG_VIBRA_PWM_SET (0x47) ++ 0x00, // REG_ANAMIC_GAIN (0x48) ++ 0x00, // REG_MISC_SET_2 (0x49) ++}; ++ ++static void twl4030_dump_registers(void) ++{ ++ int i = 0; ++ u8 data; ++ ++ printk(KERN_INFO "TWL 4030 Register dump for Audio Module\n"); ++ ++ for (i = REG_CODEC_MODE; i <= REG_MISC_SET_2; i++) { ++ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &data, i); ++ printk(KERN_INFO "Register[0x%02x]=0x%02x\n", i, data); ++ } ++} ++ ++struct twl4030_priv { ++ unsigned int dummy; ++}; ++ ++/* ++ * read twl4030 register cache ++ */ ++static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, ++ unsigned int reg) ++{ ++ u8 *cache = codec->reg_cache; ++ ++ return cache[reg]; ++} ++ ++/* ++ * write twl4030 register cache ++ */ ++static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec, ++ u8 reg, u8 value) ++{ ++ u8 *cache = codec->reg_cache; ++ ++ if (reg >= TWL4030_CACHEREGNUM) ++ return; ++ cache[reg] = value; ++} ++ ++/* ++ * write to the twl4030 register space ++ */ ++static int twl4030_write(struct snd_soc_codec *codec, ++ unsigned int reg, unsigned int value) ++{ ++ twl4030_write_reg_cache(codec, reg, value); ++ return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); ++} ++ ++static void twl4030_init_chip(void) ++{ ++ unsigned char byte; ++ int i; ++ ++ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, ++ twl4030_reg[REG_CODEC_MODE] & 0xfd, REG_CODEC_MODE); ++ ++ udelay(10); /* delay for power settling */ ++ ++ for (i = REG_OPTION; i <= REG_MISC_SET_2; i++) { ++ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, twl4030_reg[i], i); ++ } ++ ++ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, ++ twl4030_reg[REG_CODEC_MODE], REG_CODEC_MODE); ++ ++ udelay(10); /* delay for power settling */ ++ ++ /* initiate offset cancellation */ ++ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, ++ twl4030_reg[REG_ANAMICL] | 0x80, REG_ANAMICL); ++ ++ /* wait for offset cancellation to complete */ ++ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, REG_ANAMICL); ++ while ((byte & 0x80) == 0x80) ++ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, REG_ANAMICL); ++ ++ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, ++ twl4030_reg[REG_MISC_SET_1] | 0x02, REG_MISC_SET_1); ++ ++} ++ ++static const struct snd_kcontrol_new twl4030_snd_controls[] = { ++ SOC_DOUBLE_R("Master Playback Volume", ++ REG_ARXL2PGA, REG_ARXR2PGA, ++ 0, 127, 0), ++ SOC_DOUBLE_R("Capture Volume", ++ REG_ATXL1PGA, REG_ATXR1PGA, ++ 0, 127, 0), ++}; ++ ++/* add non dapm controls */ ++static int twl4030_add_controls(struct snd_soc_codec *codec) ++{ ++ int err, i; ++ ++ for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) { ++ err = snd_ctl_add(codec->card, ++ snd_soc_cnew(&twl4030_snd_controls[i], ++ codec, NULL)); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { ++ SND_SOC_DAPM_INPUT("INL"), ++ SND_SOC_DAPM_INPUT("INR"), ++ ++ SND_SOC_DAPM_OUTPUT("OUTL"), ++ SND_SOC_DAPM_OUTPUT("OUTR"), ++ ++ SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0), ++ ++ SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0), ++}; ++ ++static const char *intercon[][3] = { ++ /* outputs */ ++ {"OUTL", NULL, "DACL"}, ++ {"OUTR", NULL, "DACR"}, ++ ++ /* inputs */ ++ {"ADCL", NULL, "INL"}, ++ {"ADCR", NULL, "INR"}, ++ ++ /* terminator */ ++ {NULL, NULL, NULL}, ++}; ++ ++static int twl4030_add_widgets(struct snd_soc_codec *codec) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(twl4030_dapm_widgets); i++) ++ snd_soc_dapm_new_control(codec, &twl4030_dapm_widgets[i]); ++ ++ /* set up audio path interconnects */ ++ for (i = 0; intercon[i][0] != NULL; i++) ++ snd_soc_dapm_connect_input(codec, intercon[i][0], ++ intercon[i][1], intercon[i][2]); ++ ++ snd_soc_dapm_new_widgets(codec); ++ return 0; ++} ++ ++static int twl4030_dapm_event(struct snd_soc_codec *codec, int event) ++{ ++ ++ printk(KERN_INFO "TWL4030 Audio Codec dapm event\n"); ++ switch (event) { ++ case SNDRV_CTL_POWER_D0: /* full On */ ++ break; ++ case SNDRV_CTL_POWER_D1: /* partial On */ ++ case SNDRV_CTL_POWER_D2: /* partial On */ ++ break; ++ case SNDRV_CTL_POWER_D3hot: /* off, with power */ ++ break; ++ case SNDRV_CTL_POWER_D3cold: /* off, without power */ ++ break; ++ } ++ codec->dapm_state = event; ++ ++ return 0; ++} ++ ++static void twl4030_power_up (struct snd_soc_codec *codec, u8 mode) ++{ ++ u8 popn, hsgain; ++ ++ twl4030_write(codec, REG_CODEC_MODE, mode & ~CODECPDZ); ++ twl4030_write(codec, REG_CODEC_MODE, mode | CODECPDZ); ++ udelay(10); ++ ++ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET); ++ popn &= RAMP_DELAY; ++ popn |= VMID_EN | RAMP_DELAY_161MS; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++ ++ hsgain = HSR_GAIN_0DB| HSL_GAIN_0DB; ++ twl4030_write(codec, REG_HS_GAIN_SET, hsgain); ++ ++ popn |= RAMP_EN; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++} ++ ++static void twl4030_power_down (struct snd_soc_codec *codec) ++{ ++ u8 popn, hsgain, mode; ++ ++ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET); ++ popn &= ~RAMP_EN; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++ ++ hsgain = HSR_GAIN_PWR_DOWN | HSL_GAIN_PWR_DOWN; ++ twl4030_write(codec, REG_HS_GAIN_SET, hsgain); ++ ++ popn &= ~VMID_EN; ++ twl4030_write(codec, REG_HS_POPN_SET, popn); ++ ++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE); ++ mode &= ~CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ udelay(10); ++} ++ ++ ++static int twl4030_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_device *socdev = rtd->socdev; ++ struct snd_soc_codec *codec = socdev->codec; ++ struct twl4030_priv *twl4030 = codec->private_data; ++ u8 mode, old_mode, format, old_format; ++ ++ ++ /* bit rate */ ++ old_mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE) & ~CODECPDZ; ++ mode = old_mode; ++ mode &= ~APLL_RATE; ++ switch (params_rate(params)) { ++ case 44100: ++ mode |= APLL_RATE_44100; ++ break; ++ case 48000: ++ mode |= APLL_RATE_48000; ++ break; ++ default: ++ printk(KERN_INFO "TWL4030 hw params: unknown rate %d\n", params_rate(params)); ++ return -EINVAL; ++ } ++ ++ if (mode != old_mode) { ++ /* change rate and turn codec back on */ ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ mode |= CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ } ++ ++ /* sample size */ ++ old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF); ++ format = old_format; ++ format &= ~DATA_WIDTH; ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ format |= DATA_WIDTH_16S_16W; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ format |= DATA_WIDTH_32S_24W; ++ break; ++ default: ++ printk(KERN_INFO "TWL4030 hw params: unknown format %d\n", params_format(params)); ++ return -EINVAL; ++ } ++ ++ if (format != old_format) { ++ ++ /* turn off codec before changing format */ ++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE); ++ mode &= ~CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ ++ /* change format */ ++ twl4030_write(codec, REG_AUDIO_IF, format); ++ ++ /* turn on codec */ ++ mode |= CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ } ++ return 0; ++} ++ ++static int twl4030_mute(struct snd_soc_codec_dai *dai, int mute) ++{ ++ struct snd_soc_codec *codec = dai->codec; ++ ++ u8 ldac_reg = twl4030_read_reg_cache(codec, REG_ARXL2PGA); ++ u8 rdac_reg = twl4030_read_reg_cache(codec, REG_ARXR2PGA); ++ ++ if (mute) { ++ /* printk(KERN_INFO "TWL4030 Audio Codec mute\n"); */ ++ twl4030_write(codec, REG_ARXL2PGA, 0x00); ++ twl4030_write(codec, REG_ARXR2PGA, 0x00); ++ twl4030_write_reg_cache(codec, REG_ARXL2PGA, ldac_reg); ++ twl4030_write_reg_cache(codec, REG_ARXR2PGA, rdac_reg); ++ } ++ else { ++ /* printk(KERN_INFO "TWL4030 Audio Codec unmute: %02x/%02x\n", ldac_reg, rdac_reg); */ ++ twl4030_write(codec, REG_ARXL2PGA, ldac_reg); ++ twl4030_write(codec, REG_ARXR2PGA, rdac_reg); ++ } ++ ++ return 0; ++} ++ ++static int twl4030_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, ++ unsigned int fmt) ++{ ++ struct snd_soc_codec *codec = codec_dai->codec; ++ struct twl4030_priv *twl4030 = codec->private_data; ++ u8 mode, old_format, format; ++ ++ /* get format */ ++ old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF); ++ format = old_format; ++ ++ /* set master/slave audio interface */ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBM_CFM: ++ /* printk(KERN_INFO "TWL4030 set dai fmt: master\n"); */ ++ format &= ~(AIF_SLAVE_EN); ++ format |= CLK256FS_EN; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFS: ++ /* printk(KERN_INFO "TWL4030 set dai fmt: slave\n"); */ ++ format &= ~(CLK256FS_EN); ++ format |= AIF_SLAVE_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* interface format */ ++ format &= ~AIF_FORMAT; ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ /* printk(KERN_INFO "TWL4030 set dai fmt: i2s\n"); */ ++ format |= AIF_FORMAT_CODEC; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (format != old_format) { ++ ++ /* turn off codec before changing format */ ++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE); ++ mode &= ~CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ ++ /* change format */ ++ twl4030_write(codec, REG_AUDIO_IF, format); ++ ++ mode |= CODECPDZ; ++ twl4030_write(codec, REG_CODEC_MODE, mode); ++ } ++ ++ return 0; ++} ++ ++#define TWL4030_RATES SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 ++#define TWL4030_FORMATS SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE ++ ++struct snd_soc_codec_dai twl4030_dai = { ++ .name = "twl4030", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = TWL4030_RATES, ++ .formats = TWL4030_FORMATS,}, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = TWL4030_RATES, ++ .formats = TWL4030_FORMATS,}, ++ .ops = { ++ .hw_params = twl4030_hw_params, ++ }, ++ .dai_ops = { ++ .digital_mute = twl4030_mute, ++ .set_fmt = twl4030_set_dai_fmt, ++ } ++}; ++ ++EXPORT_SYMBOL_GPL(twl4030_dai); ++ ++static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec = socdev->codec; ++ ++ printk(KERN_INFO "TWL4030 Audio Codec suspend\n"); ++ twl4030_dapm_event(codec, SNDRV_CTL_POWER_D3cold); ++ ++ return 0; ++} ++ ++static int twl4030_resume(struct platform_device *pdev) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec = socdev->codec; ++ int i; ++ u16 *cache = codec->reg_cache; ++ ++ printk(KERN_INFO "TWL4030 Audio Codec resume\n"); ++ /* Sync reg_cache with the hardware */ ++ for (i = REG_CODEC_MODE; i <= REG_MISC_SET_2; i++) { ++ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, cache[i], i); ++ } ++ twl4030_dapm_event(codec, SNDRV_CTL_POWER_D3hot); ++ twl4030_dapm_event(codec, codec->suspend_dapm_state); ++ return 0; ++} ++ ++/* ++ * initialize the driver ++ * register the mixer and dsp interfaces with the kernel ++ */ ++ ++static int twl4030_init(struct snd_soc_device *socdev) ++{ ++ struct snd_soc_codec *codec = socdev->codec; ++ int ret = 0; ++ ++ printk(KERN_INFO "TWL4030 Audio Codec init \n"); ++ ++ codec->name = "twl4030"; ++ codec->owner = THIS_MODULE; ++ codec->read = twl4030_read_reg_cache; ++ codec->write = twl4030_write; ++ codec->dapm_event = twl4030_dapm_event; ++ codec->dai = &twl4030_dai; ++ codec->num_dai = 1; ++ codec->reg_cache_size = sizeof(twl4030_reg); ++ codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), GFP_KERNEL); ++ if (codec->reg_cache == NULL) ++ return -ENOMEM; ++ ++ /* register pcms */ ++ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); ++ if (ret < 0) { ++ printk(KERN_ERR "twl4030: failed to create pcms\n"); ++ goto pcm_err; ++ } ++ ++ twl4030_add_controls(codec); ++ twl4030_add_widgets(codec); ++ ++ ret = snd_soc_register_card(socdev); ++ if (ret < 0) { ++ printk(KERN_ERR "twl4030: failed to register card\n"); ++ goto card_err; ++ } ++ ++ twl4030_init_chip(); ++ twl4030_power_up(codec, APLL_RATE_44100 | OPT_MODE); ++ ++ return ret; ++ ++card_err: ++ printk(KERN_INFO "TWL4030 Audio Codec init card error\n"); ++ snd_soc_free_pcms(socdev); ++ snd_soc_dapm_free(socdev); ++pcm_err: ++ printk(KERN_INFO "TWL4030 Audio Codec init pcm error\n"); ++ kfree(codec->reg_cache); ++ return ret; ++} ++ ++static struct snd_soc_device *twl4030_socdev; ++ ++static int twl4030_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec; ++ struct twl4030_priv *twl4030; ++ ++ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); ++ if (codec == NULL) ++ return -ENOMEM; ++ ++ twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); ++ if (twl4030 == NULL) { ++ kfree(codec); ++ return -ENOMEM; ++ } ++ ++ codec->private_data = twl4030; ++ socdev->codec = codec; ++ mutex_init(&codec->mutex); ++ INIT_LIST_HEAD(&codec->dapm_widgets); ++ INIT_LIST_HEAD(&codec->dapm_paths); ++ ++ twl4030_socdev = socdev; ++ twl4030_init(socdev); ++ ++ return 0; ++} ++ ++static int twl4030_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); ++ struct snd_soc_codec *codec = socdev->codec; ++ ++ printk(KERN_INFO "TWL4030 Audio Codec remove\n"); ++ kfree(codec->private_data); ++ kfree(codec); ++ ++ return 0; ++} ++ ++struct snd_soc_codec_device soc_codec_dev_twl4030 = { ++ .probe = twl4030_probe, ++ .remove = twl4030_remove, ++ .suspend = twl4030_suspend, ++ .resume = twl4030_resume, ++}; ++EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); ++ ++MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); ++MODULE_AUTHOR("Steve Sakoman"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h +new file mode 100644 +index 0000000..e126f96 +--- /dev/null ++++ b/sound/soc/codecs/twl4030.h +@@ -0,0 +1,152 @@ ++/* ++ * ALSA SoC TWL4030 codec driver ++ * ++ * Author: Steve Sakoman, <steve@sakoman.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef __TWL4030_AUDIO_H__ ++#define __TWL4030_AUDIO_H__ ++ ++#define REG_CODEC_MODE 0x1 ++#define REG_OPTION 0x2 ++#define REG_UNKNOWN 0x3 ++#define REG_MICBIAS_CTL 0x4 ++#define REG_ANAMICL 0x5 ++#define REG_ANAMICR 0x6 ++#define REG_AVADC_CTL 0x7 ++#define REG_ADCMICSEL 0x8 ++#define REG_DIGMIXING 0x9 ++#define REG_ATXL1PGA 0xA ++#define REG_ATXR1PGA 0xB ++#define REG_AVTXL2PGA 0xC ++#define REG_AVTXR2PGA 0xD ++#define REG_AUDIO_IF 0xE ++#define REG_VOICE_IF 0xF ++#define REG_ARXR1PGA 0x10 ++#define REG_ARXL1PGA 0x11 ++#define REG_ARXR2PGA 0x12 ++#define REG_ARXL2PGA 0x13 ++#define REG_VRXPGA 0x14 ++#define REG_VSTPGA 0x15 ++#define REG_VRX2ARXPGA 0x16 ++#define REG_AVDAC_CTL 0x17 ++#define REG_ARX2VTXPGA 0x18 ++#define REG_ARXL1_APGA_CTL 0x19 ++#define REG_ARXR1_APGA_CTL 0x1A ++#define REG_ARXL2_APGA_CTL 0x1B ++#define REG_ARXR2_APGA_CTL 0x1C ++#define REG_ATX2ARXPGA 0x1D ++#define REG_BT_IF 0x1E ++#define REG_BTPGA 0x1F ++#define REG_BTSTPGA 0x20 ++#define REG_EAR_CTL 0x21 ++#define REG_HS_SEL 0x22 ++#define REG_HS_GAIN_SET 0x23 ++#define REG_HS_POPN_SET 0x24 ++#define REG_PREDL_CTL 0x25 ++#define REG_PREDR_CTL 0x26 ++#define REG_PRECKL_CTL 0x27 ++#define REG_PRECKR_CTL 0x28 ++#define REG_HFL_CTL 0x29 ++#define REG_HFR_CTL 0x2A ++#define REG_ALC_CTL 0x2B ++#define REG_ALC_SET1 0x2C ++#define REG_ALC_SET2 0x2D ++#define REG_BOOST_CTL 0x2E ++#define REG_SOFTVOL_CTL 0x2F ++#define REG_DTMF_FREQSEL 0x30 ++#define REG_DTMF_TONEXT1H 0x31 ++#define REG_DTMF_TONEXT1L 0x32 ++#define REG_DTMF_TONEXT2H 0x33 ++#define REG_DTMF_TONEXT2L 0x34 ++#define REG_DTMF_TONOFF 0x35 ++#define REG_DTMF_WANONOFF 0x36 ++#define REG_I2S_RX_SCRAMBLE_H 0x37 ++#define REG_I2S_RX_SCRAMBLE_M 0x38 ++#define REG_I2S_RX_SCRAMBLE_L 0x39 ++#define REG_APLL_CTL 0x3A ++#define REG_DTMF_CTL 0x3B ++#define REG_DTMF_PGA_CTL2 0x3C ++#define REG_DTMF_PGA_CTL1 0x3D ++#define REG_MISC_SET_1 0x3E ++#define REG_PCMBTMUX 0x3F ++#define REG_RX_PATH_SEL 0x43 ++#define REG_VDL_APGA_CTL 0x44 ++#define REG_VIBRA_CTL 0x45 ++#define REG_VIBRA_SET 0x46 ++#define REG_VIBRA_PWM_SET 0x47 ++#define REG_ANAMIC_GAIN 0x48 ++#define REG_MISC_SET_2 0x49 ++ ++#define TWL4030_CACHEREGNUM REG_MISC_SET_2 + 1 ++ ++/* Bitfield Definitions */ ++ ++/* CODEC_MODE (0x01) Fields */ ++ ++#define APLL_RATE 0xF0 ++#define APLL_RATE_8000 0x00 ++#define APLL_RATE_11025 0x10 ++#define APLL_RATE_12000 0x20 ++#define APLL_RATE_16000 0x40 ++#define APLL_RATE_22050 0x50 ++#define APLL_RATE_24000 0x60 ++#define APLL_RATE_32000 0x80 ++#define APLL_RATE_44100 0x90 ++#define APLL_RATE_48000 0xa0 ++#define SEL_16K 0x04 ++#define CODECPDZ 0x02 ++#define OPT_MODE 0x01 ++ ++/* AUDIO_IF (0x0E) Fields */ ++ ++#define AIF_SLAVE_EN 0x80 ++#define DATA_WIDTH 0x60 ++#define DATA_WIDTH_16S_16W 0x00 ++#define DATA_WIDTH_32S_16W 0x40 ++#define DATA_WIDTH_32S_24W 0x60 ++#define AIF_FORMAT 0x18 ++#define AIF_FORMAT_CODEC 0x00 ++#define AIF_FORMAT_LEFT 0x08 ++#define AIF_FORMAT_RIGHT 0x10 ++#define AIF_FORMAT_TDM 0x18 ++#define AIF_TRI_EN 0x04 ++#define CLK256FS_EN 0x02 ++#define AIF_EN 0x01 ++ ++/* HS_GAIN_SET (0x23) Fields */ ++ ++#define HSR_GAIN 0x0c ++#define HSR_GAIN_PWR_DOWN 0x00 ++#define HSR_GAIN_PLUS_6DB 0x04 ++#define HSR_GAIN_0DB 0x08 ++#define HSR_GAIN_MINUS_6DB 0x0c ++#define HSL_GAIN 0x0c ++#define HSL_GAIN_PWR_DOWN 0x00 ++#define HSL_GAIN_PLUS_6DB 0x01 ++#define HSL_GAIN_0DB 0x02 ++#define HSL_GAIN_MINUS_6DB 0x03 ++ ++/* HS_POPN_SET (0x24) Fields */ ++ ++#define VMID_EN 0x40 ++#define EXTMUTE 0x20 ++#define RAMP_DELAY 0x1C ++#define RAMP_DELAY_20MS 0x00 ++#define RAMP_DELAY_40MS 0x04 ++#define RAMP_DELAY_81MS 0x08 ++#define RAMP_DELAY_161MS 0x0c ++#define RAMP_DELAY_323MS 0x10 ++#define RAMP_DELAY_645MS 0x14 ++#define RAMP_DELAY_1291MS 0x18 ++#define RAMP_DELAY_2581MS 0x1c ++#define RAMP_EN 0x02 ++ ++extern struct snd_soc_codec_dai twl4030_dai; ++extern struct snd_soc_codec_device soc_codec_dev_twl4030; ++ ++#endif /* End of __TWL4030_AUDIO_H__ */ +diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig +index 0230d83..8703cea 100644 +--- a/sound/soc/omap/Kconfig ++++ b/sound/soc/omap/Kconfig +@@ -16,4 +16,20 @@ config SND_OMAP_SOC_N810 + help + Say Y if you want to add support for SoC audio on Nokia N810. + ++config SND_OMAP_SOC_OMAP3EVM ++ tristate "SoC Audio support for OMAP3 EVM" ++ depends on SND_OMAP_SOC && MACH_OMAP3EVM ++ select SND_OMAP_SOC_MCBSP ++ select SND_SOC_TWL4030 ++ help ++ Say Y if you want to add support for SoC audio on the OMAP3 EVM. ++ ++config SND_OMAP_SOC_OMAP3BEAGLE ++ tristate "SoC Audio support for OMAP3 Beagle" ++ depends on SND_OMAP_SOC && MACH_OMAP3_BEAGLE ++ select SND_OMAP_SOC_MCBSP ++ select SND_SOC_TWL4030 ++ help ++ Say Y if you want to add support for SoC audio on the OMAP3 Beagle. ++ + endmenu +diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile +index d8d8d58..638a240 100644 +--- a/sound/soc/omap/Makefile ++++ b/sound/soc/omap/Makefile +@@ -7,5 +7,10 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o + + # OMAP Machine Support + snd-soc-n810-objs := n810.o ++snd-soc-omap3evm-objs := omap3evm.o ++snd-soc-omap3beagle-objs := omap3beagle.o + + obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o ++obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o ++obj-$(CONFIG_SND_OMAP_SOC_OMAP3BEAGLE) += snd-soc-omap3beagle.o ++ +diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c +new file mode 100644 +index 0000000..878f894 +--- /dev/null ++++ b/sound/soc/omap/omap3beagle.c +@@ -0,0 +1,142 @@ ++/* ++ * omap3beagle.c -- SoC audio for OMAP3 Beagle ++ * ++ * Author: Steve Sakoman <steve@sakoman.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++ ++#include <asm/mach-types.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/gpio.h> ++#include <asm/arch/mcbsp.h> ++ ++#include "omap-mcbsp.h" ++#include "omap-pcm.h" ++#include "../codecs/twl4030.h" ++ ++static int omap3beagle_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; ++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; ++ int ret; ++ ++ /* Set codec DAI configuration */ ++ ret = codec_dai->dai_ops.set_fmt(codec_dai, ++ SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM); ++ if (ret < 0) { ++ printk(KERN_INFO "can't set codec DAI configuration\n"); ++ return ret; ++ } ++ ++ /* Set cpu DAI configuration */ ++ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, ++ SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM); ++ if (ret < 0) { ++ printk(KERN_INFO "can't set cpu DAI configuration\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static struct snd_soc_ops omap3beagle_ops = { ++ .hw_params = omap3beagle_hw_params, ++}; ++ ++/* Digital audio interface glue - connects codec <--> CPU */ ++static struct snd_soc_dai_link omap3beagle_dai = { ++ .name = "TWL4030", ++ .stream_name = "TWL4030", ++ .cpu_dai = &omap_mcbsp_dai[0], ++ .codec_dai = &twl4030_dai, ++ .ops = &omap3beagle_ops, ++}; ++ ++/* Audio machine driver */ ++static struct snd_soc_machine snd_soc_machine_omap3beagle = { ++ .name = "omap3beagle", ++ .dai_link = &omap3beagle_dai, ++ .num_links = 1, ++}; ++ ++/* Audio subsystem */ ++static struct snd_soc_device omap3beagle_snd_devdata = { ++ .machine = &snd_soc_machine_omap3beagle, ++ .platform = &omap_soc_platform, ++ .codec_dev = &soc_codec_dev_twl4030, ++}; ++ ++static struct platform_device *omap3beagle_snd_device; ++ ++static int __init omap3beagle_soc_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "OMAP3 Beagle SoC init\n"); ++ if (!machine_is_omap3_beagle()) { ++ printk(KERN_INFO "Not OMAP3 Beagle!\n"); ++ return -ENODEV; ++ } ++ ++ omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); ++ if (!omap3beagle_snd_device) { ++ printk(KERN_INFO "Platform device allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata); ++ omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev; ++ *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */ ++ ++ ret = platform_device_add(omap3beagle_snd_device); ++ if (ret) ++ goto err1; ++ ++ return 0; ++ ++err1: ++ printk(KERN_INFO "Unable to add platform device\n"); ++ platform_device_put(omap3beagle_snd_device); ++ ++ return ret; ++} ++ ++static void __exit omap3beagle_soc_exit(void) ++{ ++ printk(KERN_INFO "OMAP3 Beagle SoC exit\n"); ++ platform_device_unregister(omap3beagle_snd_device); ++} ++ ++module_init(omap3beagle_soc_init); ++module_exit(omap3beagle_soc_exit); ++ ++MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); ++MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c +new file mode 100644 +index 0000000..a64c788 +--- /dev/null ++++ b/sound/soc/omap/omap3evm.c +@@ -0,0 +1,142 @@ ++/* ++ * omap3evm.c -- SoC audio for OMAP3 EVM ++ * ++ * Author: Steve Sakoman <steve@sakoman.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++ ++#include <asm/mach-types.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/gpio.h> ++#include <asm/arch/mcbsp.h> ++ ++#include "omap-mcbsp.h" ++#include "omap-pcm.h" ++#include "../codecs/twl4030.h" ++ ++static int omap3evm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; ++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; ++ int ret; ++ ++ /* Set codec DAI configuration */ ++ ret = codec_dai->dai_ops.set_fmt(codec_dai, ++ SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM); ++ if (ret < 0) { ++ printk(KERN_INFO "can't set codec DAI configuration\n"); ++ return ret; ++ } ++ ++ /* Set cpu DAI configuration */ ++ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, ++ SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM); ++ if (ret < 0) { ++ printk(KERN_INFO "can't set cpu DAI configuration\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static struct snd_soc_ops omap3evm_ops = { ++ .hw_params = omap3evm_hw_params, ++}; ++ ++/* Digital audio interface glue - connects codec <--> CPU */ ++static struct snd_soc_dai_link omap3evm_dai = { ++ .name = "TWL4030", ++ .stream_name = "TWL4030", ++ .cpu_dai = &omap_mcbsp_dai[0], ++ .codec_dai = &twl4030_dai, ++ .ops = &omap3evm_ops, ++}; ++ ++/* Audio machine driver */ ++static struct snd_soc_machine snd_soc_machine_omap3evm = { ++ .name = "omap3evm", ++ .dai_link = &omap3evm_dai, ++ .num_links = 1, ++}; ++ ++/* Audio subsystem */ ++static struct snd_soc_device omap3evm_snd_devdata = { ++ .machine = &snd_soc_machine_omap3evm, ++ .platform = &omap_soc_platform, ++ .codec_dev = &soc_codec_dev_twl4030, ++}; ++ ++static struct platform_device *omap3evm_snd_device; ++ ++static int __init omap3evm_soc_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "OMAP3 EVM SoC init\n"); ++ if (!machine_is_omap3evm()) { ++ printk(KERN_INFO "Not OMAP3 EVM!\n"); ++ return -ENODEV; ++ } ++ ++ omap3evm_snd_device = platform_device_alloc("soc-audio", -1); ++ if (!omap3evm_snd_device) { ++ printk(KERN_INFO "Platform device allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata); ++ omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev; ++ *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1; /* McBSP2 */ ++ ++ ret = platform_device_add(omap3evm_snd_device); ++ if (ret) ++ goto err1; ++ ++ return 0; ++ ++err1: ++ printk(KERN_INFO "Unable to add platform device\n"); ++ platform_device_put(omap3evm_snd_device); ++ ++ return ret; ++} ++ ++static void __exit omap3evm_soc_exit(void) ++{ ++ printk(KERN_INFO "OMAP3 EVM SoC exit\n"); ++ platform_device_unregister(omap3evm_snd_device); ++} ++ ++module_init(omap3evm_soc_init); ++module_exit(omap3evm_soc_exit); ++ ++MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); ++MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM"); ++MODULE_LICENSE("GPL"); diff --git a/packages/linux/linux-omap/timer-suppression.patch b/packages/linux/linux-omap/timer-suppression.patch new file mode 100644 index 0000000000..04362c96e3 --- /dev/null +++ b/packages/linux/linux-omap/timer-suppression.patch @@ -0,0 +1,43 @@ +diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c +index b854a89..26f5569 100644 +--- a/kernel/time/tick-sched.c ++++ b/kernel/time/tick-sched.c +@@ -253,6 +253,16 @@ void tick_nohz_stop_sched_tick(void) + + /* Schedule the tick, if we are at least one jiffie off */ + if ((long)delta_jiffies >= 1) { ++ /* ++ * calculate the expiry time for the next timer wheel ++ * timer ++ */ ++ expires = ktime_add_ns(last_update, tick_period.tv64 * ++ delta_jiffies); ++ ++ /* Skip reprogram of event if its not changed */ ++ if(ts->tick_stopped && ktime_equal(expires, dev->next_event)) ++ goto out2; + + if (delta_jiffies > 1) + cpu_set(cpu, nohz_cpu_mask); +@@ -304,12 +314,7 @@ void tick_nohz_stop_sched_tick(void) + goto out; + } + +- /* +- * calculate the expiry time for the next timer wheel +- * timer +- */ +- expires = ktime_add_ns(last_update, tick_period.tv64 * +- delta_jiffies); ++ /* Mark expiries */ + ts->idle_expires = expires; + + if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { +@@ -328,6 +333,7 @@ void tick_nohz_stop_sched_tick(void) + tick_do_update_jiffies64(ktime_get()); + cpu_clear(cpu, nohz_cpu_mask); + } ++out2: + raise_softirq_irqoff(TIMER_SOFTIRQ); + out: + ts->next_jiffies = next_jiffies; diff --git a/packages/linux/linux-omap/touchscreen.patch b/packages/linux/linux-omap/touchscreen.patch new file mode 100644 index 0000000000..2325c401e4 --- /dev/null +++ b/packages/linux/linux-omap/touchscreen.patch @@ -0,0 +1,22 @@ +diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c +index d8109ae..f8ce669 100644 +--- a/arch/arm/mach-omap2/board-omap3evm.c ++++ b/arch/arm/mach-omap2/board-omap3evm.c +@@ -128,8 +128,16 @@ static int ads7846_get_pendown_state(void) + } + + struct ads7846_platform_data ads7846_config = { ++ .x_max = 0x0fff, ++ .y_max = 0x0fff, ++ .x_plate_ohms = 180, ++ .pressure_max = 255, ++ .debounce_max = 10, ++ .debounce_tol = 3, ++ .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, ++ .settle_delay_usecs = 150, + }; + + static struct omap2_mcspi_device_config ads7846_mcspi_config = { + |