Merge "msm: clock-8960: Restore 192MHz clock support SDC clocks" into msm-3.0
diff --git a/Documentation/sound/alsa/compress/snd_compress_data.txt b/Documentation/sound/alsa/compress/snd_compress_data.txt
new file mode 100644
index 0000000..98e2cc9
--- /dev/null
+++ b/Documentation/sound/alsa/compress/snd_compress_data.txt
@@ -0,0 +1,187 @@
+ snd_compress_data.txt
+ =====================
+ Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+ Vinod Koul <vinod.koul@linux.intel.com>
+
+Overview
+
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compability break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+Requirements
+
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+ a header per file, per frame, or no header at all. The payload size
+ may vary from frame-to-frame. As a result, it is not possible to
+ estimate reliably the duration of audio buffers when handling
+ compressed data. Dedicated mechanisms are required to allow for
+ reliable audio-video synchronization, which requires precise
+ reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+ of the sampling rate, number of channels and bits per sample. In
+ contrast, compressed data comes in a variety of formats. Audio DSPs
+ may also provide support for a limited number of audio encoders and
+ decoders embedded in firmware, or may support more choices through
+ dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+ popular formats used for audio and video capture and playback. It is
+ likely that as audio compression technology advances, new formats
+ will be added.
+
+- Handling of multiple configurations. Even for a given format like
+ AAC, some implementations may support AAC multichannel but HE-AAC
+ stereo. Likewise WMA10 level M3 may require too much memory and cpu
+ cycles. The new API needs to provide a generic way of listing these
+ formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+ hardware acceleration, where PCM samples are provided back to
+ user-space for additional processing. This API focuses instead on
+ streaming compressed data to a DSP, with the assumption that the
+ decoded samples are routed to a physical output or logical back-end.
+
+ - Complexity hiding. Existing user-space multimedia frameworks all
+ have existing enums/structures for each compressed format. This new
+ API assumes the existence of a platform-specific compatibility layer
+ to expose, translate and make use of the capabilities of the audio
+ DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+ applications are not supposed to make use of this API.
+
+
+Design
+
+The new API shares a number of concepts with with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+- get_codecs
+This routine returns the list of audio formats supported. Querying the
+codecs on a capture stream will return encoders, decoders will be
+listed for playback streams.
+
+- get_codec_caps
+For each codec, this routine returns a list of capabilities. The
+intent is to make sure all the capabilities correspond to valid
+settings, and to minimize the risks of configuration failures. For
+example, for a complex codec such as AAC, the number of channels
+supported may depend on a specific profile. If the capabilities were
+exposed with a single descriptor, it may happen that a specific
+combination of profiles/channels/formats may not be
+supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+it is likely that some implementations make the list of capabilities
+dynamic and dependent on existing workloads.
+
+- set_params
+This routine sets the configuration chosen for a specific codec. The
+most important field in the parameters is the codec type; in most
+cases decoders will ignore other fields, while encoders will strictly
+comply to the settings
+
+- get_params
+This routines returns the actual settings used by the DSP. Changes to
+the settings should remain the exception.
+
+- get_timestamp
+The timestamp becomes a multiple field structure. It lists the number
+of bytes transferred, the number of samples processed and the number
+of samples rendered/grabbed. All these values can be used to determine
+the avarage bitrate, figure out if the ring buffer needs to be
+refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+Not supported:
+
+- Support for VoIP/circuit-switched calls is not the target of this
+ API. Support for dynamic bit-rate changes would require a tight
+ coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+ additional interface to let the decoder synthesize data when frames
+ are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+ compressed data interface will be considered as regular ALSA devices
+
+Instead,
+ offloaded processing will be considered as regular ALSA devices;
+ volume changes and routing information will be provided with regular
+ ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+ manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+ above. It is possible to route the output of a decoder to a capture
+ stream, or even implement transcoding capabilities. This routing
+ would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+ hooks to query the utilization of the audio DSP, nor any premption
+ mechanisms.
+
+- No notion of underun/overrun. Since the bytes written are compressed
+ in nature and data written/read doesn't translate directly to
+ rendered output in time, this does not deal with underrun/overun and
+ maybe dealt in user-library
+
+Credits:
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Harsha Priya for her work on intel_sst compressed API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+ demonstrating and quantifying the benefits of audio offload on a
+ real platform.
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 3e754fc..f617aff 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -55,6 +55,7 @@
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_SUSPEND is not set
+CONFIG_HOTPLUG_CPU=y
CONFIG_NET=y
CONFIG_UNIX=y
CONFIG_INET=y
diff --git a/arch/arm/configs/msm7627_defconfig b/arch/arm/configs/msm7627_defconfig
index 7da4daf..4aabe08 100644
--- a/arch/arm/configs/msm7627_defconfig
+++ b/arch/arm/configs/msm7627_defconfig
@@ -288,13 +288,20 @@
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_LATENCYTOP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PAGEALLOC=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_CRYPTO_SHA256=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/board-mahimahi-smb329.c b/arch/arm/mach-msm/board-mahimahi-smb329.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 1435774..aada890 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -1072,7 +1072,7 @@
#define MSM_PMEM_MDP_SIZE 0x1900000
#define MSM7x25A_MSM_PMEM_MDP_SIZE 0x1000000
-#define MSM_PMEM_ADSP_SIZE 0x1000000
+#define MSM_PMEM_ADSP_SIZE 0x2000000
#define MSM7x25A_MSM_PMEM_ADSP_SIZE 0xB91000
diff --git a/arch/arm/mach-msm/board-msm7x30-regulator.c b/arch/arm/mach-msm/board-msm7x30-regulator.c
index 0ca7f16..5329bbe 100644
--- a/arch/arm/mach-msm/board-msm7x30-regulator.c
+++ b/arch/arm/mach-msm/board-msm7x30-regulator.c
@@ -274,7 +274,7 @@
* name id supp min uV max uV R P A B V S */
PCOM_VREG_SMP(smps0, 3, NULL, 500000, 1500000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_SMP(smps1, 4, NULL, 500000, 1500000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_SMP(smps2, 28, NULL, 1225000, 1225000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_SMP(smps2, 28, NULL, 1300000, 1300000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_SMP(smps3, 29, NULL, 1800000, 1800000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_SMP(smps4, 43, NULL, 2200000, 2200000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo00, 5, NULL, 1200000, 1200000, 0, -1, 0, 0, 0, 0),
@@ -282,7 +282,7 @@
PCOM_VREG_LDO(ldo03, 19, NULL, 1800000, 3000000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo04, 9, NULL, 2850000, 2850000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo05, 18, NULL, 2850000, 2850000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_LDO(ldo06, 16, NULL, 3075000, 3075000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_LDO(ldo06, 16, NULL, 3075000, 3400000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo07, 44, NULL, 1800000, 1800000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo08, 32, NULL, 1800000, 1800000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo09, 8, NULL, 2050000, 2050000, 0, -1, 0, 0, 0, 0),
@@ -291,16 +291,16 @@
PCOM_VREG_LDO(ldo12, 34, NULL, 1800000, 1800000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo13, 15, NULL, 2900000, 2900000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo14, 24, NULL, 2850000, 2850000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_LDO(ldo15, 23, NULL, 3100000, 3100000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_LDO(ldo15, 23, NULL, 3050000, 3100000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo16, 35, NULL, 2600000, 2600000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo17, 36, NULL, 2600000, 2600000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo18, 37, NULL, 2200000, 2200000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo19, 45, NULL, 2500000, 2500000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_LDO(ldo20, 38, NULL, 1500000, 1500000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_LDO(ldo20, 38, NULL, 1500000, 1800000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo21, 39, NULL, 1100000, 1100000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo22, 40, NULL, 1300000, 1300000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo23, 22, NULL, 1350000, 1350000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_LDO(ldo24, 41, NULL, 1225000, 1225000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_LDO(ldo24, 41, NULL, 1200000, 1200000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo25, 42, NULL, 1200000, 1200000, 0, -1, 0, 0, 0, 0),
/* Low-voltage switches */
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index eda29cd..d73f612 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -37,6 +37,7 @@
#include <linux/input/cy8c_ts.h>
#include <linux/msm_adc.h>
#include <linux/dma-mapping.h>
+#include <linux/regulator/consumer.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -331,56 +332,43 @@
};
static struct kobject *properties_kobj;
+static struct regulator_bulk_data cyttsp_regs[] = {
+ { .supply = "ldo8", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "ldo15", .min_uV = 3050000, .max_uV = 3100000 },
+};
#define CYTTSP_TS_GPIO_IRQ 150
static int cyttsp_platform_init(struct i2c_client *client)
{
int rc = -EINVAL;
- struct vreg *vreg_ldo8, *vreg_ldo15;
- vreg_ldo8 = vreg_get(NULL, "gp7");
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
- if (!vreg_ldo8) {
- pr_err("%s: VREG L8 get failed\n", __func__);
- return rc;
- }
-
- rc = vreg_set_level(vreg_ldo8, 1800);
if (rc) {
- pr_err("%s: VREG L8 set failed\n", __func__);
- goto l8_put;
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ goto out;
}
- rc = vreg_enable(vreg_ldo8);
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+
if (rc) {
- pr_err("%s: VREG L8 enable failed\n", __func__);
- goto l8_put;
+ pr_err("%s: could not set regulator voltages: %d\n", __func__,
+ rc);
+ goto regs_free;
}
- vreg_ldo15 = vreg_get(NULL, "gp6");
+ rc = regulator_bulk_enable(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
- if (!vreg_ldo15) {
- pr_err("%s: VREG L15 get failed\n", __func__);
- goto l8_disable;
- }
-
- rc = vreg_set_level(vreg_ldo15, 3050);
if (rc) {
- pr_err("%s: VREG L15 set failed\n", __func__);
- goto l8_disable;
- }
-
- rc = vreg_enable(vreg_ldo15);
- if (rc) {
- pr_err("%s: VREG L15 enable failed\n", __func__);
- goto l8_disable;
+ pr_err("%s: could not enable regulators: %d\n", __func__, rc);
+ goto regs_free;
}
/* check this device active by reading first byte/register */
rc = i2c_smbus_read_byte_data(client, 0x01);
if (rc < 0) {
pr_err("%s: i2c sanity check failed\n", __func__);
- goto l8_disable;
+ goto regs_disable;
}
rc = gpio_tlmm_config(GPIO_CFG(CYTTSP_TS_GPIO_IRQ, 0, GPIO_CFG_INPUT,
@@ -388,7 +376,7 @@
if (rc) {
pr_err("%s: Could not configure gpio %d\n",
__func__, CYTTSP_TS_GPIO_IRQ);
- goto l8_disable;
+ goto regs_disable;
}
/* virtual keys */
@@ -404,10 +392,11 @@
return CY_OK;
-l8_disable:
- vreg_disable(vreg_ldo8);
-l8_put:
- vreg_put(vreg_ldo8);
+regs_disable:
+ regulator_bulk_disable(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+regs_free:
+ regulator_bulk_free(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+out:
return rc;
}
@@ -1371,58 +1360,54 @@
pr_info("%s: power off amplifier\n", __func__);
}
-static struct vreg *snddev_vreg_ncp, *snddev_vreg_gp4;
+static struct regulator_bulk_data snddev_regs[] = {
+ { .supply = "gp4", .min_uV = 2600000, .max_uV = 2600000 },
+ { .supply = "ncp", .min_uV = 1800000, .max_uV = 1800000 },
+};
-void msm_snddev_hsed_voltage_on(void)
+static int __init snddev_hsed_voltage_init(void)
{
int rc;
- snddev_vreg_gp4 = vreg_get(NULL, "gp4");
- if (IS_ERR(snddev_vreg_gp4)) {
- pr_err("%s: vreg_get(%s) failed (%ld)\n",
- __func__, "gp4", PTR_ERR(snddev_vreg_gp4));
- return;
- }
- rc = vreg_enable(snddev_vreg_gp4);
- if (rc)
- pr_err("%s: vreg_enable(gp4) failed (%d)\n", __func__, rc);
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(snddev_regs), snddev_regs);
- snddev_vreg_ncp = vreg_get(NULL, "ncp");
- if (IS_ERR(snddev_vreg_ncp)) {
- pr_err("%s: vreg_get(%s) failed (%ld)\n",
- __func__, "ncp", PTR_ERR(snddev_vreg_ncp));
- return;
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ goto out;
}
- rc = vreg_enable(snddev_vreg_ncp);
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(snddev_regs), snddev_regs);
+
+ if (rc) {
+ pr_err("%s: could not set regulator voltages: %d\n",
+ __func__, rc);
+ goto regs_free;
+ }
+
+ return 0;
+
+regs_free:
+ regulator_bulk_free(ARRAY_SIZE(snddev_regs), snddev_regs);
+out:
+ return rc;
+}
+
+
+void msm_snddev_hsed_voltage_on(void)
+{
+ int rc = regulator_bulk_enable(ARRAY_SIZE(snddev_regs), snddev_regs);
+
if (rc)
- pr_err("%s: vreg_enable(ncp) failed (%d)\n", __func__, rc);
+ pr_err("%s: could not enable regulators: %d\n", __func__, rc);
}
void msm_snddev_hsed_voltage_off(void)
{
- int rc;
+ int rc = regulator_bulk_disable(ARRAY_SIZE(snddev_regs), snddev_regs);
- if (IS_ERR(snddev_vreg_ncp)) {
- pr_err("%s: vreg_get(%s) failed (%ld)\n",
- __func__, "ncp", PTR_ERR(snddev_vreg_ncp));
- return;
+ if (rc) {
+ pr_err("%s: could not disable regulators: %d\n", __func__, rc);
}
- rc = vreg_disable(snddev_vreg_ncp);
- if (rc)
- pr_err("%s: vreg_disable(ncp) failed (%d)\n", __func__, rc);
- vreg_put(snddev_vreg_ncp);
-
- if (IS_ERR(snddev_vreg_gp4)) {
- pr_err("%s: vreg_get(%s) failed (%ld)\n",
- __func__, "gp4", PTR_ERR(snddev_vreg_gp4));
- return;
- }
- rc = vreg_disable(snddev_vreg_gp4);
- if (rc)
- pr_err("%s: vreg_disable(gp4) failed (%d)\n", __func__, rc);
-
- vreg_put(snddev_vreg_gp4);
-
}
static unsigned aux_pcm_gpio_on[] = {
@@ -1605,10 +1590,9 @@
VER_UNSUPPORTED = 0xFF
};
-
-static struct vreg *vreg_marimba_1;
-static struct vreg *vreg_marimba_2;
-static struct vreg *vreg_marimba_3;
+static struct regulator *vreg_marimba_1;
+static struct regulator *vreg_marimba_2;
+static struct regulator *vreg_bahama;
static struct msm_gpio timpani_reset_gpio_cfg[] = {
{ GPIO_CFG(TIMPANI_RESET_GPIO, 0, GPIO_CFG_OUTPUT,
@@ -1666,34 +1650,33 @@
if (rc < 0)
goto out;
- rc = vreg_enable(vreg_marimba_1);
+ rc = regulator_enable(vreg_marimba_1);
if (rc) {
- printk(KERN_ERR "%s: vreg_enable() = %d\n",
- __func__, rc);
+ pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
goto out;
}
- rc = vreg_enable(vreg_marimba_2);
+
+ rc = regulator_enable(vreg_marimba_2);
if (rc) {
- printk(KERN_ERR "%s: vreg_enable() = %d\n",
- __func__, rc);
- goto fail_disable_vreg_marimba_1;
+ pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+ goto disable_marimba_1;
}
rc = gpio_direction_output(TIMPANI_RESET_GPIO, 1);
if (rc < 0) {
- printk(KERN_ERR
- "%s: gpio_direction_output failed (%d)\n",
+ pr_err("%s: gpio_direction_output failed (%d)\n",
__func__, rc);
msm_gpios_free(timpani_reset_gpio_cfg,
ARRAY_SIZE(timpani_reset_gpio_cfg));
- vreg_disable(vreg_marimba_2);
- } else
- goto out;
+ goto disable_marimba_2;
+ }
+ return 0;
-fail_disable_vreg_marimba_1:
- vreg_disable(vreg_marimba_1);
-
+disable_marimba_2:
+ regulator_disable(vreg_marimba_2);
+disable_marimba_1:
+ regulator_disable(vreg_marimba_1);
out:
return rc;
};
@@ -1702,23 +1685,18 @@
{
int rc;
- rc = vreg_disable(vreg_marimba_1);
- if (rc) {
- printk(KERN_ERR "%s: return val: %d\n",
- __func__, rc);
- }
- rc = vreg_disable(vreg_marimba_2);
- if (rc) {
- printk(KERN_ERR "%s: return val: %d\n",
- __func__, rc);
- }
+ rc = regulator_disable(vreg_marimba_2);
+ if (rc)
+ pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
+
+ rc = regulator_disable(vreg_marimba_1);
+ if (rc)
+ pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
rc = gpio_direction_output(TIMPANI_RESET_GPIO, 0);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: gpio_direction_output failed (%d)\n",
+ if (rc < 0)
+ pr_err("%s: gpio_direction_output failed (%d)\n",
__func__, rc);
- }
msm_gpios_free(timpani_reset_gpio_cfg,
ARRAY_SIZE(timpani_reset_gpio_cfg));
@@ -1767,13 +1745,10 @@
static unsigned int msm_bahama_setup_power(void)
{
- int rc;
+ int rc = regulator_enable(vreg_bahama);
- rc = vreg_enable(vreg_marimba_3);
- if (rc) {
- printk(KERN_ERR "%s: vreg_enable() = %d\n",
- __func__, rc);
- }
+ if (rc)
+ pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
return rc;
};
@@ -1783,11 +1758,11 @@
int rc = 0;
if (value != BAHAMA_ID) {
- rc = vreg_disable(vreg_marimba_3);
- if (rc) {
- printk(KERN_ERR "%s: return val: %d\n",
+ rc = regulator_disable(vreg_bahama);
+
+ if (rc)
+ pr_err("%s: regulator_disable failed (%d)\n",
__func__, rc);
- }
}
return rc;
@@ -1817,39 +1792,42 @@
{
int rc;
- rc = vreg_enable(vreg_marimba_1);
+ rc = regulator_enable(vreg_marimba_1);
if (rc) {
- printk(KERN_ERR "%s: vreg_enable() = %d \n",
- __func__, rc);
+ pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
goto out;
}
- rc = vreg_enable(vreg_marimba_2);
+
+ rc = regulator_enable(vreg_marimba_2);
if (rc) {
- printk(KERN_ERR "%s: vreg_enable() = %d \n",
- __func__, rc);
- goto out;
+ pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+ goto disable_marimba_1;
}
if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
rc = msm_gpios_request_enable(marimba_svlte_config_clock,
ARRAY_SIZE(marimba_svlte_config_clock));
if (rc < 0) {
- printk(KERN_ERR
- "%s: msm_gpios_request_enable failed (%d)\n",
+ pr_err("%s: msm_gpios_request_enable failed (%d)\n",
__func__, rc);
- return rc;
+ goto disable_marimba_2;
}
rc = gpio_direction_output(GPIO_PIN
(marimba_svlte_config_clock->gpio_cfg), 0);
if (rc < 0) {
- printk(KERN_ERR
- "%s: gpio_direction_output failed (%d)\n",
+ pr_err("%s: gpio_direction_output failed (%d)\n",
__func__, rc);
- return rc;
+ goto disable_marimba_2;
}
}
+ return 0;
+
+disable_marimba_2:
+ regulator_disable(vreg_marimba_2);
+disable_marimba_1:
+ regulator_disable(vreg_marimba_1);
out:
return rc;
};
@@ -1858,16 +1836,13 @@
{
int rc;
- rc = vreg_disable(vreg_marimba_1);
- if (rc) {
- printk(KERN_ERR "%s: return val: %d\n",
- __func__, rc);
- }
- rc = vreg_disable(vreg_marimba_2);
- if (rc) {
- printk(KERN_ERR "%s: return val: %d \n",
- __func__, rc);
- }
+ rc = regulator_disable(vreg_marimba_2);
+ if (rc)
+ pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
+
+ rc = regulator_disable(vreg_marimba_1);
+ if (rc)
+ pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
};
static int bahama_present(void)
@@ -1888,81 +1863,89 @@
}
}
-struct vreg *fm_regulator;
+struct regulator *fm_regulator;
static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
{
- int rc;
+ int rc, voltage;
uint32_t irqcfg;
const char *id = "FMPW";
int bahama_not_marimba = bahama_present();
- if (bahama_not_marimba == -1) {
- printk(KERN_WARNING "%s: bahama_present: %d\n",
+ if (bahama_not_marimba < 0) {
+ pr_warn("%s: bahama_present: %d\n",
__func__, bahama_not_marimba);
- return -ENODEV;
+ rc = -ENODEV;
+ goto out;
}
- if (bahama_not_marimba)
- fm_regulator = vreg_get(NULL, "s3");
- else
- fm_regulator = vreg_get(NULL, "s2");
+ if (bahama_not_marimba) {
+ fm_regulator = regulator_get(NULL, "s3");
+ voltage = 1800000;
+ } else {
+ fm_regulator = regulator_get(NULL, "s2");
+ voltage = 1300000;
+ }
if (IS_ERR(fm_regulator)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(fm_regulator));
- return -1;
+ rc = PTR_ERR(fm_regulator);
+ pr_err("%s: regulator_get failed (%d)\n", __func__, rc);
+ goto out;
}
- if (!bahama_not_marimba) {
- rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 1300);
+ rc = regulator_set_voltage(fm_regulator, voltage, voltage);
- if (rc < 0) {
- printk(KERN_ERR "%s: voltage level vote failed (%d)\n",
- __func__, rc);
- return rc;
- }
- }
- rc = vreg_enable(fm_regulator);
if (rc) {
- printk(KERN_ERR "%s: vreg_enable() = %d\n",
- __func__, rc);
- return rc;
+ pr_err("%s: regulator_set_voltage failed (%d)\n", __func__, rc);
+ goto regulator_free;
}
- rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
- PMAPP_CLOCK_VOTE_ON);
- if (rc < 0) {
- printk(KERN_ERR "%s: clock vote failed (%d)\n",
- __func__, rc);
- goto fm_clock_vote_fail;
+ rc = regulator_enable(fm_regulator);
+
+ if (rc) {
+ pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+ goto regulator_free;
}
+
+ rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO, PMAPP_CLOCK_VOTE_ON);
+
+ if (rc < 0) {
+ pr_err("%s: clock vote failed (%d)\n", __func__, rc);
+ goto regulator_disable;
+ }
+
/*Request the Clock Using GPIO34/AP2MDM_MRMBCK_EN in case
of svlte*/
- if (machine_is_msm8x55_svlte_surf() ||
- machine_is_msm8x55_svlte_ffa()) {
+ if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
rc = marimba_gpio_config(1);
- if (rc < 0)
- printk(KERN_ERR "%s: clock enable for svlte : %d\n",
- __func__, rc);
+ if (rc < 0) {
+ pr_err("%s: clock enable for svlte : %d\n",
+ __func__, rc);
+ goto clock_devote;
+ }
}
irqcfg = GPIO_CFG(147, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA);
rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
if (rc) {
- printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n",
- __func__, irqcfg, rc);
+ pr_err("%s: gpio_tlmm_config(%#x)=%d\n", __func__, irqcfg, rc);
rc = -EIO;
- goto fm_gpio_config_fail;
+ goto gpio_deconfig;
}
return 0;
-fm_gpio_config_fail:
- pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
- PMAPP_CLOCK_VOTE_OFF);
-fm_clock_vote_fail:
- vreg_disable(fm_regulator);
- return rc;
+gpio_deconfig:
+ if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa())
+ marimba_gpio_config(0);
+clock_devote:
+ pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO, PMAPP_CLOCK_VOTE_OFF);
+regulator_disable:
+ regulator_disable(fm_regulator);
+regulator_free:
+ regulator_put(fm_regulator);
+ fm_regulator = NULL;
+out:
+ return rc;
};
static void fm_radio_shutdown(struct marimba_fm_platform_data *pdata)
@@ -1974,48 +1957,36 @@
int bahama_not_marimba = bahama_present();
if (bahama_not_marimba == -1) {
- printk(KERN_WARNING "%s: bahama_present: %d\n",
- __func__, bahama_not_marimba);
+ pr_warn("%s: bahama_present: %d\n",
+ __func__, bahama_not_marimba);
return;
}
rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
if (rc) {
- printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n",
- __func__, irqcfg, rc);
+ pr_err("%s: gpio_tlmm_config(%#x)=%d\n", __func__, irqcfg, rc);
}
- if (fm_regulator != NULL) {
- rc = vreg_disable(fm_regulator);
+ if (!IS_ERR_OR_NULL(fm_regulator)) {
+ rc = regulator_disable(fm_regulator);
- if (rc) {
- printk(KERN_ERR "%s: return val: %d\n",
- __func__, rc);
- }
+ if (rc)
+ pr_err("%s: return val: %d\n", __func__, rc);
+
+ regulator_put(fm_regulator);
fm_regulator = NULL;
}
rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
PMAPP_CLOCK_VOTE_OFF);
if (rc < 0)
- printk(KERN_ERR "%s: clock_vote return val: %d\n",
- __func__, rc);
+ pr_err("%s: clock_vote return val: %d\n", __func__, rc);
/*Disable the Clock Using GPIO34/AP2MDM_MRMBCK_EN in case
of svlte*/
- if (machine_is_msm8x55_svlte_surf() ||
- machine_is_msm8x55_svlte_ffa()) {
+ if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
rc = marimba_gpio_config(0);
if (rc < 0)
- printk(KERN_ERR "%s: clock disable for svlte : %d\n",
- __func__, rc);
- }
-
-
- if (!bahama_not_marimba) {
- rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 0);
-
- if (rc < 0)
- printk(KERN_ERR "%s: vreg level vote return val: %d\n",
- __func__, rc);
+ pr_err("%s: clock disable for svlte : %d\n",
+ __func__, rc);
}
}
@@ -2042,82 +2013,60 @@
#define BAHAMA_SLAVE_ID_QMEMBIST_ADDR 0x7B
static const char *tsadc_id = "MADC";
-static const char *vregs_tsadc_name[] = {
- "gp12",
- "s2",
-};
-static struct vreg *vregs_tsadc[ARRAY_SIZE(vregs_tsadc_name)];
-static const char *vregs_timpani_tsadc_name[] = {
- "s3",
- "gp12",
- "gp16"
+static struct regulator_bulk_data regs_tsadc_marimba[] = {
+ { .supply = "gp12", .min_uV = 2200000, .max_uV = 2200000 },
+ { .supply = "s2", .min_uV = 1300000, .max_uV = 1300000 },
};
-static struct vreg *vregs_timpani_tsadc[ARRAY_SIZE(vregs_timpani_tsadc_name)];
+
+static struct regulator_bulk_data regs_tsadc_timpani[] = {
+ { .supply = "s3", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "gp12", .min_uV = 2200000, .max_uV = 2200000 },
+ { .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+};
+
+static struct regulator_bulk_data *regs_tsadc;
+static int regs_tsadc_count;
static int marimba_tsadc_power(int vreg_on)
{
- int i, rc = 0;
+ int rc = 0;
int tsadc_adie_type = adie_get_detected_codec_type();
- if (tsadc_adie_type == TIMPANI_ID) {
- for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
- if (!vregs_timpani_tsadc[i]) {
- pr_err("%s: vreg_get %s failed(%d)\n",
- __func__, vregs_timpani_tsadc_name[i], rc);
- goto vreg_fail;
- }
-
- rc = vreg_on ? vreg_enable(vregs_timpani_tsadc[i]) :
- vreg_disable(vregs_timpani_tsadc[i]);
- if (rc < 0) {
- pr_err("%s: vreg %s %s failed(%d)\n",
- __func__, vregs_timpani_tsadc_name[i],
- vreg_on ? "enable" : "disable", rc);
- goto vreg_fail;
- }
- }
- /* Vote for D0 and D1 buffer */
+ switch (tsadc_adie_type) {
+ case TIMPANI_ID:
rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_D1,
vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
if (rc) {
pr_err("%s: unable to %svote for d1 clk\n",
__func__, vreg_on ? "" : "de-");
- goto do_vote_fail;
+ goto D1_vote_fail;
}
+
+ /* fall through */
+ case MARIMBA_ID:
rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
if (rc) {
pr_err("%s: unable to %svote for d1 clk\n",
__func__, vreg_on ? "" : "de-");
- goto do_vote_fail;
+ goto D0_vote_fail;
}
- } else if (tsadc_adie_type == MARIMBA_ID) {
- for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
- if (!vregs_tsadc[i]) {
- pr_err("%s: vreg_get %s failed (%d)\n",
- __func__, vregs_tsadc_name[i], rc);
- goto vreg_fail;
- }
- rc = vreg_on ? vreg_enable(vregs_tsadc[i]) :
- vreg_disable(vregs_tsadc[i]);
- if (rc < 0) {
- pr_err("%s: vreg %s %s failed (%d)\n",
- __func__, vregs_tsadc_name[i],
- vreg_on ? "enable" : "disable", rc);
- goto vreg_fail;
- }
+ WARN_ON(regs_tsadc_count == 0);
+
+ rc = vreg_on ?
+ regulator_bulk_enable(regs_tsadc_count, regs_tsadc) :
+ regulator_bulk_disable(regs_tsadc_count, regs_tsadc);
+
+ if (rc) {
+ pr_err("%s: regulator %sable failed: %d\n",
+ __func__, vreg_on ? "en" : "dis", rc);
+ goto regulator_switch_fail;
}
- /* If marimba vote for DO buffer */
- rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
- vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
- if (rc) {
- pr_err("%s: unable to %svote for d0 clk\n",
- __func__, vreg_on ? "" : "de-");
- goto do_vote_fail;
- }
- } else {
+
+ break;
+ default:
pr_err("%s:Adie %d not supported\n",
__func__, tsadc_adie_type);
return -ENODEV;
@@ -2127,112 +2076,69 @@
return 0;
-do_vote_fail:
-vreg_fail:
- while (i) {
- if (vreg_on) {
- if (tsadc_adie_type == TIMPANI_ID)
- vreg_disable(vregs_timpani_tsadc[--i]);
- else if (tsadc_adie_type == MARIMBA_ID)
- vreg_disable(vregs_tsadc[--i]);
- } else {
- if (tsadc_adie_type == TIMPANI_ID)
- vreg_enable(vregs_timpani_tsadc[--i]);
- else if (tsadc_adie_type == MARIMBA_ID)
- vreg_enable(vregs_tsadc[--i]);
- }
- }
-
- return rc;
-}
-
-static int marimba_tsadc_vote(int vote_on)
-{
- int rc = 0;
-
- if (adie_get_detected_codec_type() == MARIMBA_ID) {
- int level = vote_on ? 1300 : 0;
- rc = pmapp_vreg_level_vote(tsadc_id, PMAPP_VREG_S2, level);
- if (rc < 0)
- pr_err("%s: vreg level %s failed (%d)\n",
- __func__, vote_on ? "on" : "off", rc);
- }
-
+regulator_switch_fail:
+ pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
+ vreg_on ? PMAPP_CLOCK_VOTE_OFF : PMAPP_CLOCK_VOTE_ON);
+D0_vote_fail:
+ if (tsadc_adie_type == TIMPANI_ID)
+ pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_D1,
+ vreg_on ? PMAPP_CLOCK_VOTE_OFF : PMAPP_CLOCK_VOTE_ON);
+D1_vote_fail:
return rc;
}
static int marimba_tsadc_init(void)
{
- int i, rc = 0;
+ int rc = 0;
int tsadc_adie_type = adie_get_detected_codec_type();
- if (tsadc_adie_type == TIMPANI_ID) {
- for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
- vregs_timpani_tsadc[i] = vreg_get(NULL,
- vregs_timpani_tsadc_name[i]);
- if (IS_ERR(vregs_timpani_tsadc[i])) {
- pr_err("%s: vreg get %s failed (%ld)\n",
- __func__, vregs_timpani_tsadc_name[i],
- PTR_ERR(vregs_timpani_tsadc[i]));
- rc = PTR_ERR(vregs_timpani_tsadc[i]);
- goto vreg_get_fail;
- }
- }
- } else if (tsadc_adie_type == MARIMBA_ID) {
- for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
- vregs_tsadc[i] = vreg_get(NULL, vregs_tsadc_name[i]);
- if (IS_ERR(vregs_tsadc[i])) {
- pr_err("%s: vreg get %s failed (%ld)\n",
- __func__, vregs_tsadc_name[i],
- PTR_ERR(vregs_tsadc[i]));
- rc = PTR_ERR(vregs_tsadc[i]);
- goto vreg_get_fail;
- }
- }
- } else {
+ switch (tsadc_adie_type) {
+ case MARIMBA_ID:
+ regs_tsadc = regs_tsadc_marimba;
+ regs_tsadc_count = ARRAY_SIZE(regs_tsadc_marimba);
+ break;
+ case TIMPANI_ID:
+ regs_tsadc = regs_tsadc_timpani;
+ regs_tsadc_count = ARRAY_SIZE(regs_tsadc_timpani);
+ break;
+ default:
pr_err("%s:Adie %d not supported\n",
__func__, tsadc_adie_type);
- return -ENODEV;
+ rc = -ENODEV;
+ goto out;
+ }
+
+ rc = regulator_bulk_get(NULL, regs_tsadc_count, regs_tsadc);
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ rc = regulator_bulk_set_voltage(regs_tsadc_count, regs_tsadc);
+ if (rc) {
+ pr_err("%s: could not set regulator voltages: %d\n",
+ __func__, rc);
+ goto vreg_free;
}
return 0;
-vreg_get_fail:
- while (i) {
- if (tsadc_adie_type == TIMPANI_ID)
- vreg_put(vregs_timpani_tsadc[--i]);
- else if (tsadc_adie_type == MARIMBA_ID)
- vreg_put(vregs_tsadc[--i]);
- }
+vreg_free:
+ regulator_bulk_free(regs_tsadc_count, regs_tsadc);
+out:
+ regs_tsadc = NULL;
+ regs_tsadc_count = 0;
return rc;
}
static int marimba_tsadc_exit(void)
{
- int i, rc = 0;
- int tsadc_adie_type = adie_get_detected_codec_type();
+ regulator_bulk_free(regs_tsadc_count, regs_tsadc);
+ regs_tsadc_count = 0;
+ regs_tsadc = NULL;
- if (tsadc_adie_type == TIMPANI_ID) {
- for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
- if (vregs_tsadc[i])
- vreg_put(vregs_timpani_tsadc[i]);
- }
- } else if (tsadc_adie_type == MARIMBA_ID) {
- for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
- if (vregs_tsadc[i])
- vreg_put(vregs_tsadc[i]);
- }
- rc = pmapp_vreg_level_vote(tsadc_id, PMAPP_VREG_S2, 0);
- if (rc < 0)
- pr_err("%s: vreg level off failed (%d)\n",
- __func__, rc);
- } else {
- pr_err("%s:Adie %d not supported\n",
- __func__, tsadc_adie_type);
- rc = -ENODEV;
- }
-
- return rc;
+ return 0;
}
@@ -2252,7 +2158,6 @@
.marimba_tsadc_power = marimba_tsadc_power,
.init = marimba_tsadc_init,
.exit = marimba_tsadc_exit,
- .level_vote = marimba_tsadc_vote,
.tsadc_prechg_en = true,
.can_wakeup = false,
.setup = {
@@ -2271,39 +2176,47 @@
.tssc_data = &msm_ts_data,
};
-static struct vreg *vreg_codec_s4;
+static struct regulator_bulk_data codec_regs[] = {
+ { .supply = "s4", .min_uV = 2200000, .max_uV = 2200000 },
+};
+
+static int __init msm_marimba_codec_init(void)
+{
+ int rc = regulator_bulk_get(NULL, ARRAY_SIZE(codec_regs), codec_regs);
+
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ goto out;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(codec_regs), codec_regs);
+ if (rc) {
+ pr_err("%s: could not set regulator voltages: %d\n",
+ __func__, rc);
+ goto reg_free;
+ }
+
+ return rc;
+
+reg_free:
+ regulator_bulk_free(ARRAY_SIZE(codec_regs), codec_regs);
+out:
+ return rc;
+}
+
static int msm_marimba_codec_power(int vreg_on)
{
- int rc = 0;
+ int rc = vreg_on ?
+ regulator_bulk_enable(ARRAY_SIZE(codec_regs), codec_regs) :
+ regulator_bulk_disable(ARRAY_SIZE(codec_regs), codec_regs);
- if (!vreg_codec_s4) {
-
- vreg_codec_s4 = vreg_get(NULL, "s4");
-
- if (IS_ERR(vreg_codec_s4)) {
- printk(KERN_ERR "%s: vreg_get() failed (%ld)\n",
- __func__, PTR_ERR(vreg_codec_s4));
- rc = PTR_ERR(vreg_codec_s4);
- goto vreg_codec_s4_fail;
- }
+ if (rc) {
+ pr_err("%s: could not %sable regulators: %d",
+ __func__, vreg_on ? "en" : "dis", rc);
+ return rc;
}
- if (vreg_on) {
- rc = vreg_enable(vreg_codec_s4);
- if (rc)
- printk(KERN_ERR "%s: vreg_enable() = %d \n",
- __func__, rc);
- goto vreg_codec_s4_fail;
- } else {
- rc = vreg_disable(vreg_codec_s4);
- if (rc)
- printk(KERN_ERR "%s: vreg_disable() = %d \n",
- __func__, rc);
- goto vreg_codec_s4_fail;
- }
-
-vreg_codec_s4_fail:
- return rc;
+ return 0;
}
static struct marimba_codec_platform_data mariba_codec_pdata = {
@@ -2334,29 +2247,38 @@
{
int rc;
- vreg_marimba_1 = vreg_get(NULL, "s3");
- if (IS_ERR(vreg_marimba_1)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_marimba_1));
- return;
- }
- rc = vreg_set_level(vreg_marimba_1, 1800);
+ struct regulator_bulk_data regs[] = {
+ { .supply = "s3", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+ { .supply = "usb2", .min_uV = 1800000, .max_uV = 1800000 },
+ };
- vreg_marimba_2 = vreg_get(NULL, "gp16");
- if (IS_ERR(vreg_marimba_1)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_marimba_1));
- return;
- }
- rc = vreg_set_level(vreg_marimba_2, 1200);
+ rc = msm_marimba_codec_init();
- vreg_marimba_3 = vreg_get(NULL, "usb2");
- if (IS_ERR(vreg_marimba_3)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_marimba_3));
+ if (rc) {
+ pr_err("%s: msm_marimba_codec_init failed (%d)\n",
+ __func__, rc);
return;
}
- rc = vreg_set_level(vreg_marimba_3, 1800);
+
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ return;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+
+ if (rc) {
+ pr_err("%s: could not set voltages: %d\n", __func__, rc);
+ regulator_bulk_free(ARRAY_SIZE(regs), regs);
+ return;
+ }
+
+ vreg_marimba_1 = regs[0].consumer;
+ vreg_marimba_2 = regs[1].consumer;
+ vreg_bahama = regs[2].consumer;
}
static struct marimba_codec_platform_data timpani_codec_pdata = {
@@ -2748,6 +2670,13 @@
"optnav_chip_select" },
};
+static struct regulator_bulk_data optnav_regulators[] = {
+ { .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "gp4", .min_uV = 2600000, .max_uV = 2600000 },
+ { .supply = "gp9", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "usb", .min_uV = 3300000, .max_uV = 3300000 },
+};
+
static void __iomem *virtual_optnav;
static int optnav_gpio_setup(void)
@@ -2756,6 +2685,9 @@
rc = msm_gpios_request_enable(optnav_config_data,
ARRAY_SIZE(optnav_config_data));
+ if (rc)
+ return rc;
+
/* Configure the FPGA for GPIOs */
virtual_optnav = ioremap(FPGA_OPTNAV_GPIO_ADDR, 0x4);
if (!virtual_optnav) {
@@ -2767,6 +2699,22 @@
* normal, active(enabled), output(MSM to SURF)
*/
writew(0x311E, virtual_optnav);
+
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(optnav_regulators),
+ optnav_regulators);
+ if (rc)
+ return rc;
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(optnav_regulators),
+ optnav_regulators);
+
+ if (rc)
+ goto regulator_put;
+
+ return rc;
+
+regulator_put:
+ regulator_bulk_free(ARRAY_SIZE(optnav_regulators), optnav_regulators);
return rc;
}
@@ -2775,13 +2723,9 @@
msm_gpios_disable_free(optnav_config_data,
ARRAY_SIZE(optnav_config_data));
iounmap(virtual_optnav);
+ regulator_bulk_free(ARRAY_SIZE(optnav_regulators), optnav_regulators);
}
-static struct vreg *vreg_gp7;
-static struct vreg *vreg_gp4;
-static struct vreg *vreg_gp9;
-static struct vreg *vreg_usb3_3;
-
static int optnav_enable(void)
{
int rc;
@@ -2789,80 +2733,24 @@
* Enable the VREGs L8(gp7), L10(gp4), L12(gp9), L6(usb)
* for I2C communication with keyboard.
*/
- vreg_gp7 = vreg_get(NULL, "gp7");
- rc = vreg_set_level(vreg_gp7, 1800);
- if (rc) {
- pr_err("%s: vreg_set_level failed \n", __func__);
- goto fail_vreg_gp7;
- }
- rc = vreg_enable(vreg_gp7);
- if (rc) {
- pr_err("%s: vreg_enable failed \n", __func__);
- goto fail_vreg_gp7;
- }
+ rc = regulator_bulk_enable(ARRAY_SIZE(optnav_regulators),
+ optnav_regulators);
- vreg_gp4 = vreg_get(NULL, "gp4");
- rc = vreg_set_level(vreg_gp4, 2600);
- if (rc) {
- pr_err("%s: vreg_set_level failed \n", __func__);
- goto fail_vreg_gp4;
- }
-
- rc = vreg_enable(vreg_gp4);
- if (rc) {
- pr_err("%s: vreg_enable failed \n", __func__);
- goto fail_vreg_gp4;
- }
-
- vreg_gp9 = vreg_get(NULL, "gp9");
- rc = vreg_set_level(vreg_gp9, 1800);
- if (rc) {
- pr_err("%s: vreg_set_level failed \n", __func__);
- goto fail_vreg_gp9;
- }
-
- rc = vreg_enable(vreg_gp9);
- if (rc) {
- pr_err("%s: vreg_enable failed \n", __func__);
- goto fail_vreg_gp9;
- }
-
- vreg_usb3_3 = vreg_get(NULL, "usb");
- rc = vreg_set_level(vreg_usb3_3, 3300);
- if (rc) {
- pr_err("%s: vreg_set_level failed \n", __func__);
- goto fail_vreg_3_3;
- }
-
- rc = vreg_enable(vreg_usb3_3);
- if (rc) {
- pr_err("%s: vreg_enable failed \n", __func__);
- goto fail_vreg_3_3;
- }
+ if (rc)
+ return rc;
/* Enable the chip select GPIO */
gpio_set_value(OPTNAV_CHIP_SELECT, 1);
gpio_set_value(OPTNAV_CHIP_SELECT, 0);
return 0;
-
-fail_vreg_3_3:
- vreg_disable(vreg_gp9);
-fail_vreg_gp9:
- vreg_disable(vreg_gp4);
-fail_vreg_gp4:
- vreg_disable(vreg_gp7);
-fail_vreg_gp7:
- return rc;
}
static void optnav_disable(void)
{
- vreg_disable(vreg_usb3_3);
- vreg_disable(vreg_gp9);
- vreg_disable(vreg_gp4);
- vreg_disable(vreg_gp7);
+ regulator_bulk_disable(ARRAY_SIZE(optnav_regulators),
+ optnav_regulators);
gpio_set_value(OPTNAV_CHIP_SELECT, 1);
}
@@ -2907,74 +2795,61 @@
};
#ifdef CONFIG_BOSCH_BMA150
-static struct vreg *vreg_gp6;
-static int sensors_ldo_enable(void)
+
+static struct regulator_bulk_data sensors_ldo[] = {
+ { .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "gp6", .min_uV = 3050000, .max_uV = 3100000 },
+};
+
+static int __init sensors_ldo_init(void)
{
int rc;
- /*
- * Enable the VREGs L8(gp7), L15(gp6)
- * for I2C communication with sensors.
- */
- pr_info("sensors_ldo_enable called!!\n");
- vreg_gp7 = vreg_get(NULL, "gp7");
- if (IS_ERR(vreg_gp7)) {
- pr_err("%s: vreg_get gp7 failed\n", __func__);
- rc = PTR_ERR(vreg_gp7);
- goto fail_gp7_get;
- }
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(sensors_ldo), sensors_ldo);
- rc = vreg_set_level(vreg_gp7, 1800);
if (rc) {
- pr_err("%s: vreg_set_level gp7 failed\n", __func__);
- goto fail_gp7_level;
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ goto out;
}
- rc = vreg_enable(vreg_gp7);
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+
if (rc) {
- pr_err("%s: vreg_enable gp7 failed\n", __func__);
- goto fail_gp7_level;
- }
-
- vreg_gp6 = vreg_get(NULL, "gp6");
- if (IS_ERR(vreg_gp6)) {
- pr_err("%s: vreg_get gp6 failed\n", __func__);
- rc = PTR_ERR(vreg_gp6);
- goto fail_gp6_get;
- }
-
- rc = vreg_set_level(vreg_gp6, 3050);
- if (rc) {
- pr_err("%s: vreg_set_level gp6 failed\n", __func__);
- goto fail_gp6_level;
- }
-
- rc = vreg_enable(vreg_gp6);
- if (rc) {
- pr_err("%s: vreg_enable gp6 failed\n", __func__);
- goto fail_gp6_level;
+ pr_err("%s: could not set voltages: %d\n", __func__, rc);
+ goto reg_free;
}
return 0;
-fail_gp6_level:
- vreg_put(vreg_gp6);
-fail_gp6_get:
- vreg_disable(vreg_gp7);
-fail_gp7_level:
- vreg_put(vreg_gp7);
-fail_gp7_get:
+reg_free:
+ regulator_bulk_free(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+out:
return rc;
}
+static int sensors_ldo_set(int on)
+{
+ int rc = on ?
+ regulator_bulk_enable(ARRAY_SIZE(sensors_ldo), sensors_ldo) :
+ regulator_bulk_disable(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+
+ if (rc)
+ pr_err("%s: could not %sable regulators: %d\n",
+ __func__, on ? "en" : "dis", rc);
+
+ return rc;
+}
+
+static int sensors_ldo_enable(void)
+{
+ return sensors_ldo_set(1);
+}
+
static void sensors_ldo_disable(void)
{
- pr_info("sensors_ldo_disable called!!\n");
- vreg_disable(vreg_gp6);
- vreg_put(vreg_gp6);
- vreg_disable(vreg_gp7);
- vreg_put(vreg_gp7);
+ sensors_ldo_set(0);
}
+
static struct bma150_platform_data bma150_data = {
.power_on = sensors_ldo_enable,
.power_off = sensors_ldo_disable,
@@ -3262,27 +3137,27 @@
#endif
#ifdef CONFIG_USB_MSM_OTG_72K
-static struct vreg *vreg_3p3;
+static struct regulator *vreg_3p3;
static int msm_hsusb_ldo_init(int init)
{
uint32_t version = 0;
- int def_vol = 3400;
+ int def_vol = 3400000;
version = socinfo_get_version();
if (SOCINFO_VERSION_MAJOR(version) >= 2 &&
SOCINFO_VERSION_MINOR(version) >= 1) {
- def_vol = 3075;
+ def_vol = 3075000;
pr_debug("%s: default voltage:%d\n", __func__, def_vol);
}
if (init) {
- vreg_3p3 = vreg_get(NULL, "usb");
+ vreg_3p3 = regulator_get(NULL, "usb");
if (IS_ERR(vreg_3p3))
return PTR_ERR(vreg_3p3);
- vreg_set_level(vreg_3p3, def_vol);
+ regulator_set_voltage(vreg_3p3, def_vol, def_vol);
} else
- vreg_put(vreg_3p3);
+ regulator_put(vreg_3p3);
return 0;
}
@@ -3300,14 +3175,14 @@
ldo_status = enable;
if (enable)
- return vreg_enable(vreg_3p3);
-
- return vreg_disable(vreg_3p3);
+ return regulator_enable(vreg_3p3);
+ else
+ return regulator_disable(vreg_3p3);
}
static int msm_hsusb_ldo_set_voltage(int mV)
{
- static int cur_voltage = 3400;
+ static int cur_voltage;
if (!vreg_3p3 || IS_ERR(vreg_3p3))
return -ENODEV;
@@ -3319,7 +3194,7 @@
pr_debug("%s: (%d)\n", __func__, mV);
- return vreg_set_level(vreg_3p3, mV);
+ return regulator_set_voltage(vreg_3p3, mV*1000, mV*1000);
}
#endif
@@ -3500,35 +3375,163 @@
GPIO_CFG(37, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA);
#endif
-static int gpio_set(const char *label, const char *name, int level, int on)
+static struct regulator_bulk_data hdmi_core_regs[] = {
+ { .supply = "ldo8", .min_uV = 1800000, .max_uV = 1800000 },
+};
+
+static struct regulator_bulk_data hdmi_comm_regs[] = {
+ { .supply = "ldo8", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "ldo10", .min_uV = 2600000, .max_uV = 2600000 },
+};
+
+static struct regulator_bulk_data hdmi_cec_regs[] = {
+ { .supply = "ldo17", .min_uV = 2600000, .max_uV = 2600000 },
+};
+
+static int __init hdmi_init_regs(void)
{
- struct vreg *vreg = vreg_get(NULL, label);
int rc;
- if (IS_ERR(vreg)) {
- rc = PTR_ERR(vreg);
- pr_err("%s: vreg %s get failed (%d)\n",
- __func__, name, rc);
- return rc;
- }
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_core_regs),
+ hdmi_core_regs);
- rc = vreg_set_level(vreg, level);
if (rc) {
- pr_err("%s: vreg %s set level failed (%d)\n",
- __func__, name, rc);
- return rc;
+ pr_err("%s: could not get %s regulators: %d\n",
+ __func__, "core", rc);
+ goto out;
}
- if (on)
- rc = vreg_enable(vreg);
- else
- rc = vreg_disable(vreg);
- if (rc)
- pr_err("%s: vreg %s enable failed (%d)\n",
- __func__, name, rc);
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_core_regs),
+ hdmi_core_regs);
+
+ if (rc) {
+ pr_err("%s: could not set %s voltages: %d\n",
+ __func__, "core", rc);
+ goto free_core;
+ }
+
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_comm_regs),
+ hdmi_comm_regs);
+
+ if (rc) {
+ pr_err("%s: could not get %s regulators: %d\n",
+ __func__, "comm", rc);
+ goto free_core;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_comm_regs),
+ hdmi_comm_regs);
+
+ if (rc) {
+ pr_err("%s: could not set %s voltages: %d\n",
+ __func__, "comm", rc);
+ goto free_comm;
+ }
+
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_cec_regs),
+ hdmi_cec_regs);
+
+ if (rc) {
+ pr_err("%s: could not get %s regulators: %d\n",
+ __func__, "cec", rc);
+ goto free_comm;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_cec_regs),
+ hdmi_cec_regs);
+
+ if (rc) {
+ pr_err("%s: could not set %s voltages: %d\n",
+ __func__, "cec", rc);
+ goto free_cec;
+ }
+
+ return 0;
+
+free_cec:
+ regulator_bulk_free(ARRAY_SIZE(hdmi_cec_regs), hdmi_cec_regs);
+free_comm:
+ regulator_bulk_free(ARRAY_SIZE(hdmi_comm_regs), hdmi_comm_regs);
+free_core:
+ regulator_bulk_free(ARRAY_SIZE(hdmi_core_regs), hdmi_core_regs);
+out:
return rc;
}
+static int hdmi_init_irq(void)
+{
+ int rc = msm_gpios_enable(dtv_panel_irq_gpios,
+ ARRAY_SIZE(dtv_panel_irq_gpios));
+ if (rc < 0) {
+ pr_err("%s: gpio enable failed: %d\n", __func__, rc);
+ return rc;
+ }
+ pr_info("%s\n", __func__);
+
+ return 0;
+}
+
+static int hdmi_enable_5v(int on)
+{
+ int pmic_gpio_hdmi_5v_en ;
+
+ if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
+ machine_is_msm7x30_fluid())
+ pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
+ else
+ pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
+
+ pr_info("%s: %d\n", __func__, on);
+ if (on) {
+ int rc;
+ rc = gpio_request(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en),
+ "hdmi_5V_en");
+ if (rc) {
+ pr_err("%s PMIC_GPIO_HDMI_5V_EN gpio_request failed\n",
+ __func__);
+ return rc;
+ }
+ gpio_set_value_cansleep(
+ PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 1);
+ } else {
+ gpio_set_value_cansleep(
+ PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 0);
+ gpio_free(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en));
+ }
+ return 0;
+}
+
+static int hdmi_comm_power(int on, int show)
+{
+ if (show)
+ pr_info("%s: i2c comm: %d <LDO8+LDO10>\n", __func__, on);
+ return on ?
+ regulator_bulk_enable(ARRAY_SIZE(hdmi_comm_regs),
+ hdmi_comm_regs) :
+ regulator_bulk_disable(ARRAY_SIZE(hdmi_comm_regs),
+ hdmi_comm_regs);
+}
+
+static int hdmi_core_power(int on, int show)
+{
+ if (show)
+ pr_info("%s: %d <LDO8>\n", __func__, on);
+ return on ?
+ regulator_bulk_enable(ARRAY_SIZE(hdmi_core_regs),
+ hdmi_core_regs) :
+ regulator_bulk_disable(ARRAY_SIZE(hdmi_core_regs),
+ hdmi_core_regs);
+}
+
+static int hdmi_cec_power(int on)
+{
+ pr_info("%s: %d <LDO17>\n", __func__, on);
+ return on ? regulator_bulk_enable(ARRAY_SIZE(hdmi_cec_regs),
+ hdmi_cec_regs) :
+ regulator_bulk_disable(ARRAY_SIZE(hdmi_cec_regs),
+ hdmi_cec_regs);
+}
+
#if defined(CONFIG_FB_MSM_HDMI_ADV7520_PANEL) || defined(CONFIG_BOSCH_BMA150)
/* there is an i2c address conflict between adv7520 and bma150 sensor after
* power up on fluid. As a solution, the default address of adv7520's packet
@@ -3541,7 +3544,6 @@
struct i2c_msg msgs[3];
int res;
int rc = -EINVAL;
- struct vreg *vreg_ldo8;
struct i2c_adapter *adapter;
if (machine_is_msm7x30_fluid()) {
@@ -3552,24 +3554,13 @@
}
/* turn on LDO8 */
- vreg_ldo8 = vreg_get(NULL, "gp7");
- if (!vreg_ldo8) {
- pr_err("%s: VREG L8 get failed\n", __func__);
+ rc = hdmi_core_power(1, 0);
+ if (rc) {
+ pr_err("%s: could not enable hdmi core regs: %d",
+ __func__, rc);
goto adapter_put;
}
- rc = vreg_set_level(vreg_ldo8, 1800);
- if (rc) {
- pr_err("%s: VREG L8 set failed\n", __func__);
- goto ldo8_put;
- }
-
- rc = vreg_enable(vreg_ldo8);
- if (rc) {
- pr_err("%s: VREG L8 enable failed\n", __func__);
- goto ldo8_put;
- }
-
/* change packet memory address to 0x74 */
wBuff[0] = 0x45;
wBuff[1] = 0x74;
@@ -3627,9 +3618,7 @@
return 0;
ldo8_disable:
- vreg_disable(vreg_ldo8);
-ldo8_put:
- vreg_put(vreg_ldo8);
+ hdmi_core_power(0, 0);
adapter_put:
i2c_put_adapter(adapter);
return rc;
@@ -3637,77 +3626,6 @@
fs_initcall_sync(fluid_i2c_address_fixup);
#endif
-static int hdmi_comm_power(int on, int show)
-{
- int rc = gpio_set("gp7", "LDO8", 1800, on);
- if (rc) {
- pr_warning("hdmi_comm_power: LDO8 gpio failed: rc=%d\n", rc);
- return rc;
- }
- rc = gpio_set("gp4", "LDO10", 2600, on);
- if (rc)
- pr_warning("hdmi_comm_power: LDO10 gpio failed: rc=%d\n", rc);
- if (show)
- pr_info("%s: i2c comm: %d <LDO8+LDO10>\n", __func__, on);
- return rc;
-}
-
-static int hdmi_init_irq(void)
-{
- int rc = msm_gpios_enable(dtv_panel_irq_gpios,
- ARRAY_SIZE(dtv_panel_irq_gpios));
- if (rc < 0) {
- pr_err("%s: gpio enable failed: %d\n", __func__, rc);
- return rc;
- }
- pr_info("%s\n", __func__);
-
- return 0;
-}
-
-static int hdmi_enable_5v(int on)
-{
- int pmic_gpio_hdmi_5v_en ;
-
- if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
- machine_is_msm7x30_fluid())
- pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
- else
- pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
-
- pr_info("%s: %d\n", __func__, on);
- if (on) {
- int rc;
- rc = gpio_request(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en),
- "hdmi_5V_en");
- if (rc) {
- pr_err("%s PMIC_GPIO_HDMI_5V_EN gpio_request failed\n",
- __func__);
- return rc;
- }
- gpio_set_value_cansleep(
- PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 1);
- } else {
- gpio_set_value_cansleep(
- PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 0);
- gpio_free(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en));
- }
- return 0;
-}
-
-static int hdmi_core_power(int on, int show)
-{
- if (show)
- pr_info("%s: %d <LDO8>\n", __func__, on);
- return gpio_set("gp7", "LDO8", 1800, on);
-}
-
-static int hdmi_cec_power(int on)
-{
- pr_info("%s: %d <LDO17>\n", __func__, on);
- return gpio_set("gp11", "LDO17", 2600, on);
-}
-
static bool hdmi_check_hdcp_hw_support(void)
{
if (machine_is_msm7x30_fluid())
@@ -4024,18 +3942,86 @@
},
};
+static struct regulator *mddi_ldo20;
+static struct regulator *mddi_ldo12;
+static struct regulator *mddi_ldo16;
+static struct regulator *mddi_ldo6;
+static struct regulator *mddi_lcd;
+
+static int display_common_init(void)
+{
+ struct regulator_bulk_data regs[5] = {
+ { .supply = "ldo20", /* voltage set in display_common_power */},
+ { .supply = "ldo12", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "ldo6", .min_uV = 3075000, .max_uV = 3400000 },
+ { .supply = "ldo16", .min_uV = 2600000, .max_uV = 2600000 },
+ { .supply = NULL, /* mddi_lcd, initialized below */ },
+ };
+
+ int rc = 0;
+
+ if (machine_is_msm7x30_fluid()) {
+ /* lcd: LDO8 @1.8V */
+ regs[4].supply = "ldo8";
+ regs[4].min_uV = 1800000;
+ regs[4].max_uV = 1800000;
+ } else {
+ /* lcd: LDO15 @3.1V */
+ regs[4].supply = "ldo15";
+ regs[4].min_uV = 3100000;
+ regs[4].max_uV = 3100000;
+ }
+
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+ if (rc) {
+ pr_err("%s: regulator_bulk_get failed: %d\n",
+ __func__, rc);
+ goto bail;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+ if (rc) {
+ pr_err("%s: regulator_bulk_set_voltage failed: %d\n",
+ __func__, rc);
+ goto put_regs;
+ }
+
+ mddi_ldo20 = regs[0].consumer;
+ mddi_ldo12 = regs[1].consumer;
+ mddi_ldo6 = regs[2].consumer;
+ mddi_ldo16 = regs[3].consumer;
+ mddi_lcd = regs[4].consumer;
+
+ return rc;
+
+put_regs:
+ regulator_bulk_free(ARRAY_SIZE(regs), regs);
+bail:
+ return rc;
+}
+
static int display_common_power(int on)
{
int rc = 0, flag_on = !!on;
static int display_common_power_save_on;
- struct vreg *vreg_ldo12, *vreg_ldo15 = NULL, *vreg_ldo6;
- struct vreg *vreg_ldo20, *vreg_ldo16, *vreg_ldo8 = NULL;
+ static bool display_regs_initialized;
if (display_common_power_save_on == flag_on)
return 0;
display_common_power_save_on = flag_on;
+ if (unlikely(!display_regs_initialized)) {
+ rc = display_common_init();
+ if (rc) {
+ pr_err("%s: regulator init failed: %d\n",
+ __func__, rc);
+ return rc;
+ }
+ display_regs_initialized = true;
+ }
+
+
if (on) {
/* reset Toshiba WeGA chip -- toggle reset pin -- gpio_180 */
rc = gpio_tlmm_config(wega_reset_gpio, GPIO_CFG_ENABLE);
@@ -4075,172 +4061,57 @@
}
}
- /* Toshiba WeGA power -- has 3 power source */
- /* 1.5V -- LDO20*/
- vreg_ldo20 = vreg_get(NULL, "gp13");
-
- if (IS_ERR(vreg_ldo20)) {
- rc = PTR_ERR(vreg_ldo20);
- pr_err("%s: gp13 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
-
- /* 1.8V -- LDO12 */
- vreg_ldo12 = vreg_get(NULL, "gp9");
-
- if (IS_ERR(vreg_ldo12)) {
- rc = PTR_ERR(vreg_ldo12);
- pr_err("%s: gp9 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
-
- /* 2.6V -- LDO16 */
- vreg_ldo16 = vreg_get(NULL, "gp10");
-
- if (IS_ERR(vreg_ldo16)) {
- rc = PTR_ERR(vreg_ldo16);
- pr_err("%s: gp10 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
-
- /* 3.075V -- LDO6 */
- vreg_ldo6 = vreg_get(NULL, "usb");
-
- if (IS_ERR(vreg_ldo6)) {
- rc = PTR_ERR(vreg_ldo6);
- pr_err("%s: usb vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
-
- if (machine_is_msm7x30_fluid()) {
- /* 1.8V -- LDO8 */
- vreg_ldo8 = vreg_get(NULL, "gp7");
-
- if (IS_ERR(vreg_ldo8)) {
- rc = PTR_ERR(vreg_ldo8);
- pr_err("%s: gp7 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
- } else {
- /* lcd panel power */
- /* 3.1V -- LDO15 */
- vreg_ldo15 = vreg_get(NULL, "gp6");
-
- if (IS_ERR(vreg_ldo15)) {
- rc = PTR_ERR(vreg_ldo15);
- pr_err("%s: gp6 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
- }
-
- /* For QuickLogic chip, LDO20 requires 1.8V */
- /* Toshiba chip requires 1.5V, but can tolerate 1.8V since max is 3V */
if (quickvx_mddi_client)
- rc = vreg_set_level(vreg_ldo20, 1800);
+ rc = regulator_set_voltage(mddi_ldo20, 1800000, 1800000);
else
- rc = vreg_set_level(vreg_ldo20, 1500);
+ rc = regulator_set_voltage(mddi_ldo20, 1500000, 1500000);
+
if (rc) {
- pr_err("%s: vreg LDO20 set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
-
- rc = vreg_set_level(vreg_ldo12, 1800);
- if (rc) {
- pr_err("%s: vreg LDO12 set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
-
- if (other_mddi_client) {
- rc = vreg_set_level(vreg_ldo16, 2600);
- if (rc) {
- pr_err("%s: vreg LDO16 set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
- }
-
- if (quickvx_mddi_client) {
- rc = vreg_set_level(vreg_ldo6, 3075);
- if (rc) {
- pr_err("%s: vreg LDO6 set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
- }
-
- if (machine_is_msm7x30_fluid()) {
- rc = vreg_set_level(vreg_ldo8, 1800);
- if (rc) {
- pr_err("%s: vreg LDO8 set level failed (%d)\n",
+ pr_err("%s: could not set voltage for ldo20: %d\n",
__func__, rc);
- return rc;
- }
- } else {
- rc = vreg_set_level(vreg_ldo15, 3100);
- if (rc) {
- pr_err("%s: vreg LDO15 set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
+ return rc;
}
if (on) {
- rc = vreg_enable(vreg_ldo20);
+ rc = regulator_enable(mddi_ldo20);
if (rc) {
- pr_err("%s: LDO20 vreg enable failed (%d)\n",
+ pr_err("%s: LDO20 regulator enable failed (%d)\n",
__func__, rc);
return rc;
}
- rc = vreg_enable(vreg_ldo12);
+ rc = regulator_enable(mddi_ldo12);
if (rc) {
- pr_err("%s: LDO12 vreg enable failed (%d)\n",
+ pr_err("%s: LDO12 regulator enable failed (%d)\n",
__func__, rc);
return rc;
}
if (other_mddi_client) {
- rc = vreg_enable(vreg_ldo16);
+ rc = regulator_enable(mddi_ldo16);
if (rc) {
- pr_err("%s: LDO16 vreg enable failed (%d)\n",
+ pr_err("%s: LDO16 regulator enable failed (%d)\n",
__func__, rc);
return rc;
}
}
- if (quickvx_mddi_client && quickvx_ldo_enabled) {
+ if (quickvx_ldo_enabled) {
/* Disable LDO6 during display ON */
- rc = vreg_disable(vreg_ldo6);
+ rc = regulator_disable(mddi_ldo6);
if (rc) {
- pr_err("%s: LDO6 vreg disable failed (%d)\n",
+ pr_err("%s: LDO6 regulator disable failed (%d)\n",
__func__, rc);
return rc;
}
quickvx_ldo_enabled = 0;
}
- if (machine_is_msm7x30_fluid()) {
- rc = vreg_enable(vreg_ldo8);
- if (rc) {
- pr_err("%s: LDO8 vreg enable failed (%d)\n",
- __func__, rc);
- return rc;
- }
- } else {
- rc = vreg_enable(vreg_ldo15);
- if (rc) {
- pr_err("%s: LDO15 vreg enable failed (%d)\n",
- __func__, rc);
- return rc;
- }
+ rc = regulator_enable(mddi_lcd);
+ if (rc) {
+ pr_err("%s: LCD regulator enable failed (%d)\n",
+ __func__, rc);
+ return rc;
}
mdelay(5); /* ensure power is stable */
@@ -4279,18 +4150,18 @@
}
} else {
- rc = vreg_disable(vreg_ldo20);
+ rc = regulator_disable(mddi_ldo20);
if (rc) {
- pr_err("%s: LDO20 vreg disable failed (%d)\n",
+ pr_err("%s: LDO20 regulator disable failed (%d)\n",
__func__, rc);
return rc;
}
if (other_mddi_client) {
- rc = vreg_disable(vreg_ldo16);
+ rc = regulator_disable(mddi_ldo16);
if (rc) {
- pr_err("%s: LDO16 vreg disable failed (%d)\n",
+ pr_err("%s: LDO16 regulator disable failed (%d)\n",
__func__, rc);
return rc;
}
@@ -4299,9 +4170,9 @@
if (quickvx_mddi_client && !quickvx_ldo_enabled) {
/* Enable LDO6 during display OFF for
Quicklogic chip to sleep with data retention */
- rc = vreg_enable(vreg_ldo6);
+ rc = regulator_enable(mddi_ldo6);
if (rc) {
- pr_err("%s: LDO6 vreg enable failed (%d)\n",
+ pr_err("%s: LDO6 regulator enable failed (%d)\n",
__func__, rc);
return rc;
}
@@ -4316,27 +4187,18 @@
PMIC_GPIO_QUICKVX_CLK), 0);
}
- if (machine_is_msm7x30_fluid()) {
- rc = vreg_disable(vreg_ldo8);
- if (rc) {
- pr_err("%s: LDO8 vreg disable failed (%d)\n",
- __func__, rc);
- return rc;
- }
- } else {
- rc = vreg_disable(vreg_ldo15);
- if (rc) {
- pr_err("%s: LDO15 vreg disable failed (%d)\n",
- __func__, rc);
- return rc;
- }
+ rc = regulator_disable(mddi_lcd);
+ if (rc) {
+ pr_err("%s: LCD regulator disable failed (%d)\n",
+ __func__, rc);
+ return rc;
}
mdelay(5); /* ensure power is stable */
- rc = vreg_disable(vreg_ldo12);
+ rc = regulator_disable(mddi_ldo12);
if (rc) {
- pr_err("%s: LDO12 vreg disable failed (%d)\n",
+ pr_err("%s: LDO12 regulator disable failed (%d)\n",
__func__, rc);
return rc;
}
@@ -4365,51 +4227,19 @@
static int msm_fb_mddi_client_power(u32 client_id)
{
- struct vreg *vreg_ldo20, *vreg_ldo16;
- int rc;
-
printk(KERN_NOTICE "\n client_id = 0x%x", client_id);
/* Check if it is Quicklogic client */
if (client_id == 0xc5835800) {
printk(KERN_NOTICE "\n Quicklogic MDDI client");
other_mddi_client = 0;
- vreg_ldo16 = vreg_get(NULL, "gp10");
-
- if (IS_ERR(vreg_ldo16)) {
- rc = PTR_ERR(vreg_ldo16);
- pr_err("%s: gp10 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
-
- rc = vreg_disable(vreg_ldo16);
- if (rc) {
- pr_err("%s: LDO16 vreg enable failed (%d)\n",
- __func__, rc);
- return rc;
- }
} else {
printk(KERN_NOTICE "\n Non-Quicklogic MDDI client");
quickvx_mddi_client = 0;
gpio_set_value(97, 0);
gpio_set_value_cansleep(PM8058_GPIO_PM_TO_SYS(
PMIC_GPIO_QUICKVX_CLK), 0);
-
- vreg_ldo20 = vreg_get(NULL, "gp13");
-
- if (IS_ERR(vreg_ldo20)) {
- rc = PTR_ERR(vreg_ldo20);
- pr_err("%s: gp13 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
- rc = vreg_set_level(vreg_ldo20, 1500);
- if (rc) {
- pr_err("%s: vreg LDO20 set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
}
+
return 0;
}
@@ -4574,13 +4404,18 @@
static int lcdc_panel_power(int on)
{
int flag_on = !!on;
- static int lcdc_power_save_on;
+ static int lcdc_power_save_on, lcdc_power_initialized;
if (lcdc_power_save_on == flag_on)
return 0;
lcdc_power_save_on = flag_on;
- quickvx_mddi_client = 0;
+
+ if (unlikely(!lcdc_power_initialized)) {
+ quickvx_mddi_client = 0;
+ display_common_init();
+ lcdc_power_initialized = 1;
+ }
if (machine_is_msm7x30_fluid())
return lcdc_sharp_panel_power(on);
@@ -4592,47 +4427,64 @@
.lcdc_power_save = lcdc_panel_power,
};
+static struct regulator *atv_s4, *atv_ldo9;
+
+static int __init atv_dac_power_init(void)
+{
+ int rc;
+ struct regulator_bulk_data regs[] = {
+ { .supply = "smps4", .min_uV = 2200000, .max_uV = 2200000 },
+ { .supply = "ldo9", .min_uV = 2050000, .max_uV = 2050000 },
+ };
+
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ goto bail;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+
+ if (rc) {
+ pr_err("%s: could not set voltages: %d\n", __func__, rc);
+ goto reg_free;
+ }
+
+ atv_s4 = regs[0].consumer;
+ atv_ldo9 = regs[1].consumer;
+
+reg_free:
+ regulator_bulk_free(ARRAY_SIZE(regs), regs);
+bail:
+ return rc;
+}
+
static int atv_dac_power(int on)
{
int rc = 0;
- struct vreg *vreg_s4, *vreg_ldo9;
-
- vreg_s4 = vreg_get(NULL, "s4");
- if (IS_ERR(vreg_s4)) {
- rc = PTR_ERR(vreg_s4);
- pr_err("%s: s4 vreg get failed (%d)\n",
- __func__, rc);
- return -1;
- }
- vreg_ldo9 = vreg_get(NULL, "gp1");
- if (IS_ERR(vreg_ldo9)) {
- rc = PTR_ERR(vreg_ldo9);
- pr_err("%s: ldo9 vreg get failed (%d)\n",
- __func__, rc);
- return rc;
- }
if (on) {
- rc = vreg_enable(vreg_s4);
+ rc = regulator_enable(atv_s4);
if (rc) {
pr_err("%s: s4 vreg enable failed (%d)\n",
__func__, rc);
return rc;
}
- rc = vreg_enable(vreg_ldo9);
+ rc = regulator_enable(atv_ldo9);
if (rc) {
pr_err("%s: ldo9 vreg enable failed (%d)\n",
__func__, rc);
return rc;
}
} else {
- rc = vreg_disable(vreg_ldo9);
+ rc = regulator_disable(atv_ldo9);
if (rc) {
pr_err("%s: ldo9 vreg disable failed (%d)\n",
__func__, rc);
return rc;
}
- rc = vreg_disable(vreg_s4);
+ rc = regulator_disable(atv_s4);
if (rc) {
pr_err("%s: s4 vreg disable failed (%d)\n",
__func__, rc);
@@ -4707,24 +4559,31 @@
"UART1DM_Tx" }
};
-static const char *vregs_bt_marimba_name[] = {
- "s3",
- "s2",
- "gp16",
- "wlan"
-};
-static struct vreg *vregs_bt_marimba[ARRAY_SIZE(vregs_bt_marimba_name)];
-
-static const char *vregs_bt_bahama_name[] = {
- "s3",
- "usb2",
- "s2",
- "wlan"
-};
-static struct vreg *vregs_bt_bahama[ARRAY_SIZE(vregs_bt_bahama_name)];
-
static u8 bahama_version;
+static struct regulator_bulk_data regs_bt_marimba[] = {
+ { .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
+ { .supply = "ldo24", .min_uV = 1200000, .max_uV = 1200000 },
+ { .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data regs_bt_bahama_v1[] = {
+ { .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "ldo7", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
+ { .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data regs_bt_bahama_v2[] = {
+ { .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "ldo7", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data *regs_bt;
+static int regs_bt_count;
+
static int marimba_bt(int on)
{
int rc;
@@ -4946,15 +4805,6 @@
on = on ? 1 : 0;
- bahama_version = read_bahama_ver();
-
- if (((int)bahama_version) < 0 ||
- bahama_version == VER_UNSUPPORTED) {
- dev_err(&msm_bt_power_device.dev,
- "%s: i2c failure or unsupported version: %d\n",
- __func__, bahama_version);
- return -EIO;
- }
if (bahama_version == VER_2_0) {
if (marimba_get_fm_status(&config))
@@ -4990,69 +4840,62 @@
else
marimba_set_bt_status(&config, false);
- if (bahama_version == VER_2_0 && on) { /* variant of bahama v2 */
- /* Disable s2 as bahama v2 uses internal LDO regulator */
- for (i = 0; i < ARRAY_SIZE(vregs_bt_bahama_name); i++) {
- if (!strcmp(vregs_bt_bahama_name[i], "s2")) {
- rc = vreg_disable(vregs_bt_bahama[i]);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: vreg %s disable "
- "failed (%d)\n",
- __func__,
- vregs_bt_bahama_name[i], rc);
- return -EIO;
- }
- rc = pmapp_vreg_level_vote("BTPW",
- PMAPP_VREG_S2,
- 0);
- if (rc < 0) {
- printk(KERN_ERR "%s: vreg "
- "level off failed (%d)\n",
- __func__, rc);
- return -EIO;
- }
- printk(KERN_INFO "%s: vreg disable & "
- "level off successful (%d)\n",
- __func__, rc);
- }
- }
- }
-
return 0;
}
-static int bluetooth_power_regulators(int on, int bahama_not_marimba)
+static int bluetooth_regs_init(int bahama_not_marimba)
{
- int i, rc;
- const char **vregs_name;
- struct vreg **vregs;
- int vregs_size;
+ int rc = 0;
+ struct device *const dev = &msm_bt_power_device.dev;
if (bahama_not_marimba) {
- vregs_name = vregs_bt_bahama_name;
- vregs = vregs_bt_bahama;
- vregs_size = ARRAY_SIZE(vregs_bt_bahama_name);
+ bahama_version = read_bahama_ver();
+
+ switch (bahama_version) {
+ case VER_1_0:
+ regs_bt = regs_bt_bahama_v1;
+ regs_bt_count = ARRAY_SIZE(regs_bt_bahama_v1);
+ break;
+ case VER_2_0:
+ regs_bt = regs_bt_bahama_v2;
+ regs_bt_count = ARRAY_SIZE(regs_bt_bahama_v2);
+ break;
+ case VER_UNSUPPORTED:
+ default:
+ dev_err(dev,
+ "%s: i2c failure or unsupported version: %d\n",
+ __func__, bahama_version);
+ rc = -EIO;
+ goto out;
+ }
} else {
- vregs_name = vregs_bt_marimba_name;
- vregs = vregs_bt_marimba;
- vregs_size = ARRAY_SIZE(vregs_bt_marimba_name);
+ regs_bt = regs_bt_marimba;
+ regs_bt_count = ARRAY_SIZE(regs_bt_marimba);
}
- for (i = 0; i < vregs_size; i++) {
- if (bahama_not_marimba && (bahama_version == VER_2_0) &&
- !on && !strcmp(vregs_bt_bahama_name[i], "s2"))
- continue;
- rc = on ? vreg_enable(vregs[i]) :
- vreg_disable(vregs[i]);
- if (rc < 0) {
- printk(KERN_ERR "%s: vreg %s %s failed (%d)\n",
- __func__, vregs_name[i],
- on ? "enable" : "disable", rc);
- return -EIO;
- }
+ rc = regulator_bulk_get(&msm_bt_power_device.dev,
+ regs_bt_count, regs_bt);
+ if (rc) {
+ dev_err(dev, "%s: could not get regulators: %d\n",
+ __func__, rc);
+ goto out;
}
+
+ rc = regulator_bulk_set_voltage(regs_bt_count, regs_bt);
+ if (rc) {
+ dev_err(dev, "%s: could not set voltages: %d\n",
+ __func__, rc);
+ goto reg_free;
+ }
+
return 0;
+
+reg_free:
+ regulator_bulk_free(regs_bt_count, regs_bt);
+out:
+ regs_bt_count = 0;
+ regs_bt = NULL;
+ return rc;
}
static int bluetooth_power(int on)
@@ -5068,17 +4911,16 @@
return -ENODEV;
}
- if (on) {
- rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 1300);
- if (rc < 0) {
- printk(KERN_ERR "%s: vreg level on failed (%d)\n",
- __func__, rc);
+ if (unlikely(regs_bt_count == 0)) {
+ rc = bluetooth_regs_init(bahama_not_marimba);
+ if (rc)
return rc;
- }
+ }
- rc = bluetooth_power_regulators(on, bahama_not_marimba);
- if (rc < 0)
- return -EIO;
+ if (on) {
+ rc = regulator_bulk_enable(regs_bt_count, regs_bt);
+ if (rc)
+ return rc;
rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
PMAPP_CLOCK_VOTE_ON);
@@ -5135,18 +4977,10 @@
if (rc < 0)
return -EIO;
- rc = bluetooth_power_regulators(on, bahama_not_marimba);
- if (rc < 0)
- return -EIO;
+ rc = regulator_bulk_disable(regs_bt_count, regs_bt);
+ if (rc)
+ return rc;
- if (bahama_version == VER_1_0) {
- rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 0);
- if (rc < 0) {
- printk(KERN_ERR "%s: vreg level off failed "
- "(%d)\n", __func__, rc);
- return -EIO;
- }
- }
}
out:
@@ -5157,29 +4991,7 @@
static void __init bt_power_init(void)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(vregs_bt_marimba_name); i++) {
- vregs_bt_marimba[i] = vreg_get(NULL, vregs_bt_marimba_name[i]);
- if (IS_ERR(vregs_bt_marimba[i])) {
- printk(KERN_ERR "%s: vreg get %s failed (%ld)\n",
- __func__, vregs_bt_marimba_name[i],
- PTR_ERR(vregs_bt_marimba[i]));
- return;
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(vregs_bt_bahama_name); i++) {
- vregs_bt_bahama[i] = vreg_get(NULL, vregs_bt_bahama_name[i]);
- if (IS_ERR(vregs_bt_bahama[i])) {
- printk(KERN_ERR "%s: vreg get %s failed (%ld)\n",
- __func__, vregs_bt_bahama_name[i],
- PTR_ERR(vregs_bt_bahama[i]));
- return;
- }
- }
-
- msm_bt_power_device.dev.platform_data = &bluetooth_power;
+ msm_bt_power_device.dev.platform_data = &bluetooth_power;
}
#else
#define bt_power_init(x) do {} while (0)
@@ -5415,7 +5227,7 @@
}
/*This needs to be enabled only for OEMS*/
#ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
-static struct vreg *qup_vreg;
+static struct regulator *qup_vreg;
#endif
static void
qup_i2c_gpio_config(int adap_id, int config_type)
@@ -5434,15 +5246,10 @@
printk(KERN_ERR "QUP GPIO enable failed: %d\n", rc);
/*This needs to be enabled only for OEMS*/
#ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
- if (qup_vreg) {
- int rc = vreg_set_level(qup_vreg, 1800);
+ if (!IS_ERR_OR_NULL(qup_vreg)) {
+ rc = regulator_enable(qup_vreg);
if (rc) {
- pr_err("%s: vreg LVS1 set level failed (%d)\n",
- __func__, rc);
- }
- rc = vreg_enable(qup_vreg);
- if (rc) {
- pr_err("%s: vreg_enable() = %d \n",
+ pr_err("%s: regulator_enable failed: %d\n",
__func__, rc);
}
}
@@ -5491,9 +5298,10 @@
qup_device_i2c.dev.platform_data = &qup_i2c_pdata;
/*This needs to be enabled only for OEMS*/
#ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
- qup_vreg = vreg_get(NULL, "lvsw1");
+ qup_vreg = regulator_get(&qup_device_i2c.dev, "lvsw1");
if (IS_ERR(qup_vreg)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
+ dev_err(&qup_device_i2c.dev,
+ "%s: regulator_get failed: %ld\n",
__func__, PTR_ERR(qup_vreg));
}
#endif
@@ -5516,9 +5324,6 @@
{GPIO_CFG(115, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "ebi2_busy1"},
};
-struct vreg *vreg_s3;
-struct vreg *vreg_mmc;
-
#if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT)\
|| defined(CONFIG_MMC_MSM_SDC2_SUPPORT)\
|| defined(CONFIG_MMC_MSM_SDC3_SUPPORT)\
@@ -5615,12 +5420,7 @@
},
};
-struct sdcc_vreg {
- struct vreg *vreg_data;
- unsigned level;
-};
-
-static struct sdcc_vreg sdcc_vreg_data[4];
+static struct regulator *sdcc_vreg_data[ARRAY_SIZE(sdcc_cfg_data)];
static unsigned long vreg_sts, gpio_sts;
@@ -5656,37 +5456,36 @@
static uint32_t msm_sdcc_setup_vreg(int dev_id, unsigned int enable)
{
int rc = 0;
- struct sdcc_vreg *curr;
+ struct regulator *curr = sdcc_vreg_data[dev_id - 1];
static int enabled_once[] = {0, 0, 0, 0};
- curr = &sdcc_vreg_data[dev_id - 1];
-
- if (!(test_bit(dev_id, &vreg_sts)^enable))
+ if (test_bit(dev_id, &vreg_sts) == enable)
return rc;
if (!enable || enabled_once[dev_id - 1])
return 0;
+ if (!curr)
+ return -ENODEV;
+
+ if (IS_ERR(curr))
+ return PTR_ERR(curr);
+
if (enable) {
set_bit(dev_id, &vreg_sts);
- rc = vreg_set_level(curr->vreg_data, curr->level);
- if (rc) {
- printk(KERN_ERR "%s: vreg_set_level() = %d \n",
+
+ rc = regulator_enable(curr);
+ if (rc)
+ pr_err("%s: could not enable regulator: %d\n",
__func__, rc);
- }
- rc = vreg_enable(curr->vreg_data);
- if (rc) {
- printk(KERN_ERR "%s: vreg_enable() = %d \n",
- __func__, rc);
- }
enabled_once[dev_id - 1] = 1;
} else {
clear_bit(dev_id, &vreg_sts);
- rc = vreg_disable(curr->vreg_data);
- if (rc) {
- printk(KERN_ERR "%s: vreg_disable() = %d \n",
+
+ rc = regulator_disable(curr);
+ if (rc)
+ pr_err("%s: could not disable regulator: %d\n",
__func__, rc);
- }
}
return rc;
}
@@ -5757,109 +5556,76 @@
return rc;
}
-static int mbp_setup_rf_vregs(int state)
+static struct regulator_bulk_data mbp_regs_io[2];
+static struct regulator_bulk_data mbp_regs_rf[2];
+static struct regulator_bulk_data mbp_regs_adc[1];
+static struct regulator_bulk_data mbp_regs_core[1];
+
+static int mbp_init_regs(struct device *dev)
{
- struct vreg *vreg_rf = NULL;
- struct vreg *vreg_rf_switch = NULL;
+ struct regulator_bulk_data regs[] = {
+ /* Analog and I/O regs */
+ { .supply = "gp4", .min_uV = 2600000, .max_uV = 2600000 },
+ { .supply = "s3", .min_uV = 1800000, .max_uV = 1800000 },
+ /* RF regs */
+ { .supply = "s2", .min_uV = 1300000, .max_uV = 1300000 },
+ { .supply = "rf", .min_uV = 2600000, .max_uV = 2600000 },
+ /* ADC regs */
+ { .supply = "s4", .min_uV = 2200000, .max_uV = 2200000 },
+ /* Core regs */
+ { .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+ };
+
+ struct regulator_bulk_data *regptr = regs;
int rc;
- vreg_rf = vreg_get(NULL, "s2");
- if (IS_ERR(vreg_rf)) {
- pr_err("%s: s2 vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_rf));
- return -EFAULT;
- }
- vreg_rf_switch = vreg_get(NULL, "rf");
- if (IS_ERR(vreg_rf_switch)) {
- pr_err("%s: rf vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_rf_switch));
- return -EFAULT;
+ rc = regulator_bulk_get(dev, ARRAY_SIZE(regs), regs);
+
+ if (rc) {
+ dev_err(dev, "%s: could not get regulators: %d\n",
+ __func__, rc);
+ goto out;
}
- if (state) {
- rc = vreg_set_level(vreg_rf, 1300);
- if (rc) {
- pr_err("%s: vreg s2 set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
- rc = vreg_enable(vreg_rf);
- if (rc) {
- printk(KERN_ERR "%s: vreg_enable(s2) = %d\n",
- __func__, rc);
- }
-
- rc = vreg_set_level(vreg_rf_switch, 2600);
- if (rc) {
- pr_err("%s: vreg rf switch set level failed (%d)\n",
- __func__, rc);
- return rc;
- }
- rc = vreg_enable(vreg_rf_switch);
- if (rc) {
- printk(KERN_ERR "%s: vreg_enable(rf) = %d\n",
- __func__, rc);
- }
- } else {
- (void) vreg_disable(vreg_rf);
- (void) vreg_disable(vreg_rf_switch);
+ if (rc) {
+ dev_err(dev, "%s: could not set voltages: %d\n",
+ __func__, rc);
+ goto reg_free;
}
+
+ memcpy(mbp_regs_io, regptr, sizeof(mbp_regs_io));
+ regptr += ARRAY_SIZE(mbp_regs_io);
+
+ memcpy(mbp_regs_rf, regptr, sizeof(mbp_regs_rf));
+ regptr += ARRAY_SIZE(mbp_regs_rf);
+
+ memcpy(mbp_regs_adc, regptr, sizeof(mbp_regs_adc));
+ regptr += ARRAY_SIZE(mbp_regs_adc);
+
+ memcpy(mbp_regs_core, regptr, sizeof(mbp_regs_core));
+
return 0;
+
+reg_free:
+ regulator_bulk_free(ARRAY_SIZE(regs), regs);
+out:
+ return rc;
+}
+
+static int mbp_setup_rf_vregs(int state)
+{
+ return state ?
+ regulator_bulk_enable(ARRAY_SIZE(mbp_regs_rf), mbp_regs_rf) :
+ regulator_bulk_disable(ARRAY_SIZE(mbp_regs_rf), mbp_regs_rf);
}
static int mbp_setup_vregs(int state)
{
- struct vreg *vreg_analog = NULL;
- struct vreg *vreg_io = NULL;
- int rc;
-
- vreg_analog = vreg_get(NULL, "gp4");
- if (IS_ERR(vreg_analog)) {
- pr_err("%s: gp4 vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_analog));
- return -EFAULT;
- }
- vreg_io = vreg_get(NULL, "s3");
- if (IS_ERR(vreg_io)) {
- pr_err("%s: s3 vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_io));
- return -EFAULT;
- }
- if (state) {
- rc = vreg_set_level(vreg_analog, 2600);
- if (rc) {
- pr_err("%s: vreg_set_level failed (%d)",
- __func__, rc);
- }
- rc = vreg_enable(vreg_analog);
- if (rc) {
- pr_err("%s: analog vreg enable failed (%d)",
- __func__, rc);
- }
- rc = vreg_set_level(vreg_io, 1800);
- if (rc) {
- pr_err("%s: vreg_set_level failed (%d)",
- __func__, rc);
- }
- rc = vreg_enable(vreg_io);
- if (rc) {
- pr_err("%s: io vreg enable failed (%d)",
- __func__, rc);
- }
- } else {
- rc = vreg_disable(vreg_analog);
- if (rc) {
- pr_err("%s: analog vreg disable failed (%d)",
- __func__, rc);
- }
- rc = vreg_disable(vreg_io);
- if (rc) {
- pr_err("%s: io vreg disable failed (%d)",
- __func__, rc);
- }
- }
- return rc;
+ return state ?
+ regulator_bulk_enable(ARRAY_SIZE(mbp_regs_io), mbp_regs_io) :
+ regulator_bulk_disable(ARRAY_SIZE(mbp_regs_io), mbp_regs_io);
}
static int mbp_set_tcxo_en(int enable)
@@ -5875,16 +5641,6 @@
__func__, enable ? "" : "de-");
return -EIO;
}
- if (!enable) {
- vreg_analog = vreg_get(NULL, "gp4");
- if (IS_ERR(vreg_analog)) {
- pr_err("%s: gp4 vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_analog));
- return -EFAULT;
- }
-
- (void) vreg_disable(vreg_analog);
- }
return rc;
}
@@ -5898,28 +5654,20 @@
static int mbp_set_core_voltage_en(int enable)
{
- int rc;
- struct vreg *vreg_core1p2 = NULL;
+ static bool is_enabled;
+ int rc = 0;
- vreg_core1p2 = vreg_get(NULL, "gp16");
- if (IS_ERR(vreg_core1p2)) {
- pr_err("%s: gp16 vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_core1p2));
- return -EFAULT;
- }
- if (enable) {
- rc = vreg_set_level(vreg_core1p2, 1200);
+ if (enable && !is_enabled) {
+ rc = regulator_bulk_enable(ARRAY_SIZE(mbp_regs_core),
+ mbp_regs_core);
if (rc) {
- pr_err("%s: vreg_set_level failed (%d)",
+ pr_err("%s: could not enable regulators: %d\n",
__func__, rc);
+ } else {
+ is_enabled = true;
}
- (void) vreg_enable(vreg_core1p2);
-
- return 80;
- } else {
- gpio_set_value(85, 1);
- return 0;
}
+
return rc;
}
@@ -5950,34 +5698,9 @@
static int mbp_setup_adc_vregs(int state)
{
- struct vreg *vreg_adc = NULL;
- int rc;
-
- vreg_adc = vreg_get(NULL, "s4");
- if (IS_ERR(vreg_adc)) {
- pr_err("%s: s4 vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_adc));
- return -EFAULT;
- }
- if (state) {
- rc = vreg_set_level(vreg_adc, 2200);
- if (rc) {
- pr_err("%s: vreg_set_level failed (%d)",
- __func__, rc);
- }
- rc = vreg_enable(vreg_adc);
- if (rc) {
- pr_err("%s: enable vreg adc failed (%d)",
- __func__, rc);
- }
- } else {
- rc = vreg_disable(vreg_adc);
- if (rc) {
- pr_err("%s: disable vreg adc failed (%d)",
- __func__, rc);
- }
- }
- return rc;
+ return state ?
+ regulator_bulk_enable(ARRAY_SIZE(mbp_regs_adc), mbp_regs_adc) :
+ regulator_bulk_disable(ARRAY_SIZE(mbp_regs_adc), mbp_regs_adc);
}
static int mbp_power_up(void)
@@ -6042,14 +5765,6 @@
static int mbp_power_down(void)
{
int rc;
- struct vreg *vreg_adc = NULL;
-
- vreg_adc = vreg_get(NULL, "s4");
- if (IS_ERR(vreg_adc)) {
- pr_err("%s: s4 vreg get failed (%ld)",
- __func__, PTR_ERR(vreg_adc));
- return -EFAULT;
- }
mbp_set_reset(MBP_ON);
pr_debug("%s: mbp_set_reset(MBP_ON) done\n", __func__);
@@ -6079,13 +5794,16 @@
goto exit;
pr_debug("%s: mbp_set_core_voltage_en(MBP_OFF) done\n", __func__);
- gpio_set_value(85, 1);
-
rc = mbp_set_tcxo_en(MBP_OFF);
if (rc)
goto exit;
pr_debug("%s: mbp_set_tcxo_en(MBP_OFF) done\n", __func__);
+ rc = mbp_setup_vregs(MBP_OFF);
+ if (rc)
+ goto exit;
+ pr_debug("%s: mbp_setup_vregs(MBP_OFF) done\n", __func__);
+
rc = mbp_config_gpios_pre_init(MBP_OFF);
if (rc)
goto exit;
@@ -6147,6 +5865,12 @@
goto out;
}
if (!mbp_power_init_done) {
+ rc = mbp_init_regs(dv);
+ if (rc) {
+ dev_err(dv, "%s: regulator init failed: %d\n",
+ __func__, rc);
+ goto out;
+ }
mbp_setup_power(dv, 1);
mbp_setup_power(dv, 0);
mbp_power_init_done = 1;
@@ -6285,18 +6009,32 @@
#endif
#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
-static void msm_sdc1_lvlshft_enable(void)
+static int msm_sdc1_lvlshft_enable(void)
{
+ static struct regulator *ldo5;
int rc;
/* Enable LDO5, an input to the FET that powers slot 1 */
- rc = vreg_set_level(vreg_mmc, 2850);
- if (rc)
- printk(KERN_ERR "%s: vreg_set_level() = %d \n", __func__, rc);
- rc = vreg_enable(vreg_mmc);
- if (rc)
- printk(KERN_ERR "%s: vreg_enable() = %d \n", __func__, rc);
+ ldo5 = regulator_get(NULL, "ldo5");
+
+ if (IS_ERR(ldo5)) {
+ rc = PTR_ERR(ldo5);
+ pr_err("%s: could not get ldo5: %d\n", __func__, rc);
+ goto out;
+ }
+
+ rc = regulator_set_voltage(ldo5, 2850000, 2850000);
+ if (rc) {
+ pr_err("%s: could not set ldo5 voltage: %d\n", __func__, rc);
+ goto ldo5_free;
+ }
+
+ rc = regulator_enable(ldo5);
+ if (rc) {
+ pr_err("%s: could not enable ldo5: %d\n", __func__, rc);
+ goto ldo5_free;
+ }
/* Enable GPIO 35, to turn on the FET that powers slot 1 */
rc = msm_gpios_request_enable(sdc1_lvlshft_cfg_data,
@@ -6308,35 +6046,72 @@
1);
if (rc)
printk(KERN_ERR "%s: Failed to turn on GPIO 35\n", __func__);
+
+ return 0;
+
+ldo5_free:
+ regulator_put(ldo5);
+out:
+ ldo5 = NULL;
+ return rc;
}
#endif
+static int mmc_regulator_init(int sdcc_no, const char *supply, int uV)
+{
+ int rc;
+
+ BUG_ON(sdcc_no < 1 || sdcc_no > 4);
+
+ sdcc_no--;
+
+ sdcc_vreg_data[sdcc_no] = regulator_get(NULL, supply);
+
+ if (IS_ERR(sdcc_vreg_data[sdcc_no])) {
+ rc = PTR_ERR(sdcc_vreg_data[sdcc_no]);
+ pr_err("%s: could not get regulator \"%s\": %d\n",
+ __func__, supply, rc);
+ goto out;
+ }
+
+ rc = regulator_set_voltage(sdcc_vreg_data[sdcc_no], uV, uV);
+
+ if (rc) {
+ pr_err("%s: could not set voltage for \"%s\" to %d uV: %d\n",
+ __func__, supply, uV, rc);
+ goto reg_free;
+ }
+
+ return rc;
+
+reg_free:
+ regulator_put(sdcc_vreg_data[sdcc_no]);
+out:
+ sdcc_vreg_data[sdcc_no] = NULL;
+ return rc;
+}
+
static void __init msm7x30_init_mmc(void)
{
- vreg_s3 = vreg_get(NULL, "s3");
- if (IS_ERR(vreg_s3)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_s3));
- return;
- }
-
- vreg_mmc = vreg_get(NULL, "mmc");
- if (IS_ERR(vreg_mmc)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_mmc));
- return;
- }
-
#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+ if (mmc_regulator_init(1, "s3", 1800000))
+ goto out1;
+
if (machine_is_msm7x30_fluid()) {
msm7x30_sdc1_data.ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29;
- msm_sdc1_lvlshft_enable();
+ if (msm_sdc1_lvlshft_enable()) {
+ pr_err("%s: could not enable level shift\n");
+ goto out1;
+ }
}
- sdcc_vreg_data[0].vreg_data = vreg_s3;
- sdcc_vreg_data[0].level = 1800;
+
msm_add_sdcc(1, &msm7x30_sdc1_data);
+out1:
#endif
#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+ if (mmc_regulator_init(2, "s3", 1800000))
+ goto out2;
+
if (machine_is_msm8x55_svlte_surf())
msm7x30_sdc2_data.msmsdcc_fmax = 24576000;
if (machine_is_msm8x55_svlte_surf() ||
@@ -6344,19 +6119,22 @@
msm7x30_sdc2_data.sdiowakeup_irq = MSM_GPIO_TO_INT(68);
msm7x30_sdc2_data.is_sdio_al_client = 1;
}
- sdcc_vreg_data[1].vreg_data = vreg_s3;
- sdcc_vreg_data[1].level = 1800;
+
msm_add_sdcc(2, &msm7x30_sdc2_data);
+out2:
#endif
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- sdcc_vreg_data[2].vreg_data = vreg_s3;
- sdcc_vreg_data[2].level = 1800;
+ if (mmc_regulator_init(3, "s3", 1800000))
+ goto out3;
+
msm_sdcc_setup_gpio(3, 1);
msm_add_sdcc(3, &msm7x30_sdc3_data);
+out3:
#endif
#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
- sdcc_vreg_data[3].vreg_data = vreg_mmc;
- sdcc_vreg_data[3].level = 2850;
+ if (mmc_regulator_init(4, "mmc", 2850000))
+ return;
+
msm_add_sdcc(4, &msm7x30_sdc4_data);
#endif
@@ -6468,68 +6246,50 @@
"tsc2007_irq" },
};
-static struct vreg *vreg_tsc_s3;
-static struct vreg *vreg_tsc_s2;
+static struct regulator_bulk_data tsc2007_regs[] = {
+ { .supply = "s3", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "s2", .min_uV = 1300000, .max_uV = 1300000 },
+};
static int tsc2007_init(void)
{
int rc;
- vreg_tsc_s3 = vreg_get(NULL, "s3");
- if (IS_ERR(vreg_tsc_s3)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_tsc_s3));
- return -ENODEV;
- }
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
- rc = vreg_set_level(vreg_tsc_s3, 1800);
if (rc) {
- pr_err("%s: vreg_set_level failed \n", __func__);
- goto fail_vreg_set_level;
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ goto out;
}
- rc = vreg_enable(vreg_tsc_s3);
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+
if (rc) {
- pr_err("%s: vreg_enable failed \n", __func__);
- goto fail_vreg_set_level;
+ pr_err("%s: could not set voltages: %d\n", __func__, rc);
+ goto reg_free;
}
- vreg_tsc_s2 = vreg_get(NULL, "s2");
- if (IS_ERR(vreg_tsc_s2)) {
- printk(KERN_ERR "%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_tsc_s2));
- goto fail_vreg_get;
- }
+ rc = regulator_bulk_enable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
- rc = vreg_set_level(vreg_tsc_s2, 1300);
if (rc) {
- pr_err("%s: vreg_set_level failed \n", __func__);
- goto fail_vreg_s2_level;
- }
-
- rc = vreg_enable(vreg_tsc_s2);
- if (rc) {
- pr_err("%s: vreg_enable failed \n", __func__);
- goto fail_vreg_s2_level;
+ pr_err("%s: could not enable regulators: %d\n", __func__, rc);
+ goto reg_free;
}
rc = msm_gpios_request_enable(tsc2007_config_data,
ARRAY_SIZE(tsc2007_config_data));
if (rc) {
pr_err("%s: Unable to request gpios\n", __func__);
- goto fail_gpio_req;
+ goto reg_disable;
}
return 0;
-fail_gpio_req:
- vreg_disable(vreg_tsc_s2);
-fail_vreg_s2_level:
- vreg_put(vreg_tsc_s2);
-fail_vreg_get:
- vreg_disable(vreg_tsc_s3);
-fail_vreg_set_level:
- vreg_put(vreg_tsc_s3);
+reg_disable:
+ regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+reg_free:
+ regulator_bulk_free(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+out:
return rc;
}
@@ -6549,10 +6309,9 @@
static void tsc2007_exit(void)
{
- vreg_disable(vreg_tsc_s3);
- vreg_put(vreg_tsc_s3);
- vreg_disable(vreg_tsc_s2);
- vreg_put(vreg_tsc_s2);
+
+ regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+ regulator_bulk_free(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
msm_gpios_disable_free(tsc2007_config_data,
ARRAY_SIZE(tsc2007_config_data));
@@ -6562,35 +6321,20 @@
{
int rc;
- if (enable == false) {
- rc = vreg_enable(vreg_tsc_s2);
- if (rc) {
- pr_err("%s: vreg_enable failed\n", __func__);
- return rc;
- }
- rc = vreg_enable(vreg_tsc_s3);
- if (rc) {
- pr_err("%s: vreg_enable failed\n", __func__);
- vreg_disable(vreg_tsc_s2);
- return rc;
- }
- /* Voltage settling delay */
- msleep(20);
- } else {
- rc = vreg_disable(vreg_tsc_s2);
- if (rc) {
- pr_err("%s: vreg_disable failed\n", __func__);
- return rc;
- }
- rc = vreg_disable(vreg_tsc_s3);
- if (rc) {
- pr_err("%s: vreg_disable failed\n", __func__);
- vreg_enable(vreg_tsc_s2);
- return rc;
- }
+ rc = (enable == false) ?
+ regulator_bulk_enable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs) :
+ regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+
+ if (rc) {
+ pr_err("%s: could not %sable regulators: %d\n",
+ __func__, enable ? "dis" : "en", rc);
+ return rc;
}
- return rc;
+ if (enable == false)
+ msleep(20);
+
+ return 0;
}
static struct tsc2007_platform_data tsc2007_ts_data = {
@@ -6617,36 +6361,23 @@
};
#endif
-static const char *vregs_isa1200_name[] = {
- "gp7",
- "gp10",
+static struct regulator_bulk_data regs_isa1200[] = {
+ { .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "gp10", .min_uV = 2600000, .max_uV = 2600000 },
};
-static const int vregs_isa1200_val[] = {
- 1800,
- 2600,
-};
-static struct vreg *vregs_isa1200[ARRAY_SIZE(vregs_isa1200_name)];
-
static int isa1200_power(int vreg_on)
{
- int i, rc = 0;
+ int rc = 0;
- for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) {
- if (!vregs_isa1200[i]) {
- pr_err("%s: vreg_get %s failed (%d)\n",
- __func__, vregs_isa1200_name[i], rc);
- goto vreg_fail;
- }
+ rc = vreg_on ?
+ regulator_bulk_enable(ARRAY_SIZE(regs_isa1200), regs_isa1200) :
+ regulator_bulk_disable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
- rc = vreg_on ? vreg_enable(vregs_isa1200[i]) :
- vreg_disable(vregs_isa1200[i]);
- if (rc < 0) {
- pr_err("%s: vreg %s %s failed (%d)\n",
- __func__, vregs_isa1200_name[i],
- vreg_on ? "enable" : "disable", rc);
- goto vreg_fail;
- }
+ if (rc) {
+ pr_err("%s: could not %sable regulators: %d\n",
+ __func__, vreg_on ? "en" : "dis", rc);
+ goto out;
}
/* vote for DO buffer */
@@ -6661,33 +6392,34 @@
return 0;
vreg_fail:
- while (i)
- vreg_disable(vregs_isa1200[--i]);
+ if (vreg_on)
+ regulator_bulk_disable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+ else
+ regulator_bulk_enable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+out:
return rc;
}
static int isa1200_dev_setup(bool enable)
{
- int i, rc;
+ int rc;
if (enable == true) {
- for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) {
- vregs_isa1200[i] = vreg_get(NULL,
- vregs_isa1200_name[i]);
- if (IS_ERR(vregs_isa1200[i])) {
- pr_err("%s: vreg get %s failed (%ld)\n",
- __func__, vregs_isa1200_name[i],
- PTR_ERR(vregs_isa1200[i]));
- rc = PTR_ERR(vregs_isa1200[i]);
- goto vreg_get_fail;
- }
- rc = vreg_set_level(vregs_isa1200[i],
- vregs_isa1200_val[i]);
- if (rc) {
- pr_err("%s: vreg_set_level() = %d\n",
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_isa1200),
+ regs_isa1200);
+
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n",
__func__, rc);
- goto vreg_get_fail;
- }
+ goto out;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_isa1200),
+ regs_isa1200);
+ if (rc) {
+ pr_err("%s: could not set voltages: %d\n",
+ __func__, rc);
+ goto reg_free;
}
rc = gpio_tlmm_config(GPIO_CFG(HAP_LVL_SHFT_MSM_GPIO, 0,
@@ -6696,28 +6428,27 @@
if (rc) {
pr_err("%s: Could not configure gpio %d\n",
__func__, HAP_LVL_SHFT_MSM_GPIO);
- goto vreg_get_fail;
+ goto reg_free;
}
rc = gpio_request(HAP_LVL_SHFT_MSM_GPIO, "haptics_shft_lvl_oe");
if (rc) {
pr_err("%s: unable to request gpio %d (%d)\n",
__func__, HAP_LVL_SHFT_MSM_GPIO, rc);
- goto vreg_get_fail;
+ goto reg_free;
}
gpio_set_value(HAP_LVL_SHFT_MSM_GPIO, 1);
} else {
- for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++)
- vreg_put(vregs_isa1200[i]);
-
+ regulator_bulk_free(ARRAY_SIZE(regs_isa1200), regs_isa1200);
gpio_free(HAP_LVL_SHFT_MSM_GPIO);
}
return 0;
-vreg_get_fail:
- while (i)
- vreg_put(vregs_isa1200[--i]);
+
+reg_free:
+ regulator_bulk_free(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+out:
return rc;
}
static struct isa1200_platform_data isa1200_1_pdata = {
@@ -6777,69 +6508,48 @@
}
};
-static const char *vregs_tma300_name[] = {
- "gp6",
- "gp7",
+static struct regulator_bulk_data regs_tma300[] = {
+ { .supply = "gp6", .min_uV = 3050000, .max_uV = 3100000 },
+ { .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
};
-static const int vregs_tma300_val[] = {
- 3050,
- 1800,
-};
-static struct vreg *vregs_tma300[ARRAY_SIZE(vregs_tma300_name)];
-
static int tma300_power(int vreg_on)
{
- int i, rc = -EINVAL;
+ int rc;
- for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++) {
- /* Never disable gp6 for fluid as lcd has a problem with it */
- if (!i && !vreg_on)
- continue;
- if (!vregs_tma300[i]) {
- printk(KERN_ERR "%s: vreg_get %s failed (%d)\n",
- __func__, vregs_tma300_name[i], rc);
- return rc;
- }
+ rc = vreg_on ?
+ regulator_bulk_enable(ARRAY_SIZE(regs_tma300), regs_tma300) :
+ regulator_bulk_disable(ARRAY_SIZE(regs_tma300), regs_tma300);
- rc = vreg_on ? vreg_enable(vregs_tma300[i]) :
- vreg_disable(vregs_tma300[i]);
- if (rc < 0) {
- printk(KERN_ERR "%s: vreg %s %s failed (%d)\n",
- __func__, vregs_tma300_name[i],
- vreg_on ? "enable" : "disable", rc);
- return rc;
- }
- }
-
- return 0;
+ if (rc)
+ pr_err("%s: could not %sable regulators: %d\n",
+ __func__, vreg_on ? "en" : "dis", rc);
+ return rc;
}
#define TS_GPIO_IRQ 150
static int tma300_dev_setup(bool enable)
{
- int i, rc;
+ int rc;
if (enable) {
- /* get voltage sources */
- for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++) {
- vregs_tma300[i] = vreg_get(NULL, vregs_tma300_name[i]);
- if (IS_ERR(vregs_tma300[i])) {
- pr_err("%s: vreg get %s failed (%ld)\n",
- __func__, vregs_tma300_name[i],
- PTR_ERR(vregs_tma300[i]));
- rc = PTR_ERR(vregs_tma300[i]);
- goto vreg_get_fail;
- }
- rc = vreg_set_level(vregs_tma300[i],
- vregs_tma300_val[i]);
- if (rc) {
- pr_err("%s: vreg_set_level() = %d\n",
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_tma300),
+ regs_tma300);
+
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n",
__func__, rc);
- i++;
- goto vreg_get_fail;
- }
+ goto out;
+ }
+
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_tma300),
+ regs_tma300);
+
+ if (rc) {
+ pr_err("%s: could not set voltages: %d\n",
+ __func__, rc);
+ goto reg_free;
}
/* enable interrupt gpio */
@@ -6848,7 +6558,7 @@
if (rc) {
pr_err("%s: Could not configure gpio %d\n",
__func__, TS_GPIO_IRQ);
- goto vreg_get_fail;
+ goto reg_free;
}
/* virtual keys */
@@ -6856,23 +6566,20 @@
properties_kobj = kobject_create_and_add("board_properties",
NULL);
if (!properties_kobj) {
- pr_err("%s: failed to create a kobject"
- "for board_properites\n", __func__);
+ pr_err("%s: failed to create a kobject "
+ "for board_properties\n", __func__);
rc = -ENOMEM;
- goto vreg_get_fail;
+ goto reg_free;
}
rc = sysfs_create_group(properties_kobj,
&tma300_properties_attr_group);
if (rc) {
pr_err("%s: failed to create a sysfs entry %s\n",
__func__, tma300_vkeys_attr.attr.name);
- kobject_put(properties_kobj);
- goto vreg_get_fail;
+ goto kobj_free;
}
} else {
- /* put voltage sources */
- for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++)
- vreg_put(vregs_tma300[i]);
+ regulator_bulk_free(ARRAY_SIZE(regs_tma300), regs_tma300);
/* destroy virtual keys */
if (properties_kobj) {
sysfs_remove_group(properties_kobj,
@@ -6882,9 +6589,12 @@
}
return 0;
-vreg_get_fail:
- while (i)
- vreg_put(vregs_tma300[--i]);
+kobj_free:
+ kobject_put(properties_kobj);
+ properties_kobj = NULL;
+reg_free:
+ regulator_bulk_free(ARRAY_SIZE(regs_tma300), regs_tma300);
+out:
return rc;
}
@@ -6995,6 +6705,9 @@
ARRAY_SIZE(lcdc_toshiba_spi_board_info));
#endif
+ atv_dac_power_init();
+ sensors_ldo_init();
+ hdmi_init_regs();
msm_fb_add_devices();
msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_RESET_VECTOR,
@@ -7005,6 +6718,7 @@
msm7x30_init_marimba();
#ifdef CONFIG_MSM7KV2_AUDIO
snddev_poweramp_gpio_init();
+ snddev_hsed_voltage_init();
aux_pcm_gpio_init();
#endif
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index a0a7d79..e1e922e 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -76,6 +76,7 @@
#include <linux/ion.h>
#include <mach/ion.h>
+#include <mach/mdm2.h>
#include "timer.h"
#include "devices.h"
@@ -92,6 +93,11 @@
#include "pm-boot.h"
#include "msm_watchdog.h"
+#define PLATFORM_IS_CHARM25() \
+ (machine_is_msm8960_cdp() && \
+ (socinfo_get_platform_subtype() == 1) \
+ )
+
static struct platform_device msm_fm_platform_init = {
.name = "iris_fm",
.id = -1,
@@ -2663,6 +2669,138 @@
};
#endif
+#define MDM2AP_ERRFATAL 70
+#define AP2MDM_ERRFATAL 95
+#define MDM2AP_STATUS 69
+#define AP2MDM_STATUS 94
+#define AP2MDM_PMIC_RESET_N 80
+#define AP2MDM_KPDPWR_N 81
+
+static struct gpiomux_setting ap2mdm_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdm2ap_status_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdm2ap_errfatal_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_16MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config mdm_configs[] __initdata = {
+ /* AP2MDM_STATUS */
+ {
+ .gpio = AP2MDM_STATUS,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* MDM2AP_STATUS */
+ {
+ .gpio = MDM2AP_STATUS,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
+ }
+ },
+ /* MDM2AP_ERRFATAL */
+ {
+ .gpio = MDM2AP_ERRFATAL,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
+ }
+ },
+ /* AP2MDM_ERRFATAL */
+ {
+ .gpio = AP2MDM_ERRFATAL,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* AP2MDM_KPDPWR_N */
+ {
+ .gpio = AP2MDM_KPDPWR_N,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+ }
+ },
+ /* AP2MDM_PMIC_RESET_N */
+ {
+ .gpio = AP2MDM_PMIC_RESET_N,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+ }
+ }
+};
+
+static struct resource mdm_resources[] = {
+ {
+ .start = MDM2AP_ERRFATAL,
+ .end = MDM2AP_ERRFATAL,
+ .name = "MDM2AP_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_ERRFATAL,
+ .end = AP2MDM_ERRFATAL,
+ .name = "AP2MDM_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = MDM2AP_STATUS,
+ .end = MDM2AP_STATUS,
+ .name = "MDM2AP_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_STATUS,
+ .end = AP2MDM_STATUS,
+ .name = "AP2MDM_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_PMIC_RESET_N,
+ .end = AP2MDM_PMIC_RESET_N,
+ .name = "AP2MDM_PMIC_RESET_N",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_KPDPWR_N,
+ .end = AP2MDM_KPDPWR_N,
+ .name = "AP2MDM_KPDPWR_N",
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mdm_platform_data mdm_platform_data = {
+ .mdm_version = "2.5",
+};
+
+struct platform_device mdm_device = {
+ .name = "mdm2_modem",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mdm_resources),
+ .resource = mdm_resources,
+ .dev = {
+ .platform_data = &mdm_platform_data,
+ },
+};
+
+static struct platform_device *mdm_devices[] __initdata = {
+ &mdm_device,
+};
static int __init gpiomux_init(void)
{
@@ -2710,6 +2848,11 @@
machine_is_msm8960_liquid() || machine_is_msm8960_cdp())
msm_gpiomux_install(hap_lvl_shft_config,
ARRAY_SIZE(hap_lvl_shft_config));
+
+ if (PLATFORM_IS_CHARM25())
+ msm_gpiomux_install(mdm_configs,
+ ARRAY_SIZE(mdm_configs));
+
return 0;
}
@@ -4840,6 +4983,9 @@
msm_pm_data);
change_memory_power = &msm8960_change_memory_power;
BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+
+ if (PLATFORM_IS_CHARM25())
+ platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
}
MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 8f733a9..0d2bd82 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1085,8 +1085,8 @@
return -ENOTSUPP;
}
- if ((machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) &&
- !pmic_id_notif_supported) {
+ if ((machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa() ||
+ machine_is_msm8x60_ffa()) && !pmic_id_notif_supported) {
pr_debug("%s: USB_ID is not routed to PMIC"
"on V2 ffa\n", __func__);
return -ENOTSUPP;
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 85de532..31767c3 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -39,7 +39,6 @@
#include <mach/usb_gadget_fserial.h>
#include <mach/msm_memtypes.h>
#include <mach/msm_serial_hs.h>
-#include <mach/vreg.h>
#include <mach/pmic.h>
#include <mach/socinfo.h>
#include <mach/vreg.h>
@@ -47,7 +46,7 @@
#include <mach/msm_battery.h>
#include <mach/rpc_server_handset.h>
#include <mach/socinfo.h>
-
+#include "board-msm7x27a-regulator.h"
#include "devices.h"
#include "devices-msm7x2xa.h"
#include "pm.h"
@@ -279,7 +278,7 @@
return rc;
}
-static struct vreg *fm_regulator;
+static struct regulator *fm_regulator;
static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
{
int rc = 0;
@@ -289,27 +288,25 @@
u8 value;
/* Voting for 1.8V Regulator */
- fm_regulator = vreg_get(NULL , "msme1");
+ fm_regulator = regulator_get(NULL , "msme1");
if (IS_ERR(fm_regulator)) {
- pr_err("%s: vreg get failed with : (%ld)\n",
- __func__, PTR_ERR(fm_regulator));
- return -EINVAL;
+ rc = PTR_ERR(fm_regulator);
+ pr_err("%s: could not get regulator: %d\n", __func__, rc);
+ goto out;
}
/* Set the voltage level to 1.8V */
- rc = vreg_set_level(fm_regulator, 1800);
+ rc = regulator_set_voltage(fm_regulator, 1800000, 1800000);
if (rc < 0) {
- pr_err("%s: set regulator level failed with :(%d)\n",
- __func__, rc);
- goto fm_vreg_fail;
+ pr_err("%s: could not set voltage: %d\n", __func__, rc);
+ goto reg_free;
}
/* Enabling the 1.8V regulator */
- rc = vreg_enable(fm_regulator);
+ rc = regulator_enable(fm_regulator);
if (rc) {
- pr_err("%s: enable regulator failed with :(%d)\n",
- __func__, rc);
- goto fm_vreg_fail;
+ pr_err("%s: could not enable regulator: %d\n", __func__, rc);
+ goto reg_free;
}
/* Voting for 19.2MHz clock */
@@ -318,13 +315,13 @@
if (rc < 0) {
pr_err("%s: clock vote failed with :(%d)\n",
__func__, rc);
- goto fm_clock_vote_fail;
+ goto reg_disable;
}
rc = bt_set_gpio(1);
if (rc) {
pr_err("%s: bt_set_gpio = %d", __func__, rc);
- goto fm_gpio_config_fail;
+ goto gpio_deconfig;
}
/*re-write FM Slave Id, after reset*/
value = BAHAMA_SLAVE_ID_FM_ADDR;
@@ -332,7 +329,7 @@
BAHAMA_SLAVE_ID_FM_REG, &value, 1, 0xFF);
if (rc < 0) {
pr_err("%s: FM Slave ID rewrite Failed = %d", __func__, rc);
- goto fm_gpio_config_fail;
+ goto gpio_deconfig;
}
/* Configuring the FM GPIO */
irqcfg = GPIO_CFG(FM_GPIO, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
@@ -342,21 +339,21 @@
if (rc) {
pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
__func__, irqcfg, rc);
- goto fm_gpio_config_fail;
+ goto gpio_deconfig;
}
return 0;
-fm_gpio_config_fail:
+gpio_deconfig:
pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
PMAPP_CLOCK_VOTE_OFF);
bt_set_gpio(0);
-fm_clock_vote_fail:
- vreg_disable(fm_regulator);
-
-fm_vreg_fail:
- vreg_put(fm_regulator);
-
+reg_disable:
+ regulator_disable(fm_regulator);
+reg_free:
+ regulator_put(fm_regulator);
+ fm_regulator = NULL;
+out:
return rc;
};
@@ -375,11 +372,12 @@
__func__, irqcfg, rc);
/* Releasing the 1.8V Regulator */
- if (fm_regulator != NULL) {
- rc = vreg_disable(fm_regulator);
+ if (!IS_ERR_OR_NULL(fm_regulator)) {
+ rc = regulator_disable(fm_regulator);
if (rc)
- pr_err("%s: disable regulator failed:(%d)\n",
- __func__, rc);
+ pr_err("%s: could not disable regulator: %d\n",
+ __func__, rc);
+ regulator_put(fm_regulator);
fm_regulator = NULL;
}
@@ -423,18 +421,18 @@
struct bt_vreg_info {
const char *name;
unsigned int pmapp_id;
- unsigned int level;
+ unsigned int min_level;
+ unsigned int max_level;
unsigned int is_pin_controlled;
- struct vreg *vregs;
+ struct regulator *reg;
};
static struct bt_vreg_info bt_vregs[] = {
- {"msme1", 2, 1800, 0, NULL},
- {"bt", 21, 2900, 1, NULL}
+ {"msme1", 2, 1800000, 1800000, 0, NULL},
+ {"bt", 21, 2900000, 3050000, 1, NULL}
};
static int bahama_bt(int on)
{
-
int rc = 0;
int i;
@@ -587,73 +585,94 @@
const char *id = "BTPW";
for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
- if (!bt_vregs[i].vregs) {
- pr_err("%s: vreg_get %s failed(%d)\n",
- __func__, bt_vregs[i].name, rc);
- goto vreg_fail;
+ if (IS_ERR_OR_NULL(bt_vregs[i].reg)) {
+ rc = bt_vregs[i].reg ?
+ PTR_ERR(bt_vregs[i].reg) :
+ -ENODEV;
+ dev_err(&msm_bt_power_device.dev,
+ "%s: invalid regulator handle for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_disable;
}
- rc = on ? vreg_set_level(bt_vregs[i].vregs,
- bt_vregs[i].level) : 0;
- if (rc < 0) {
- pr_err("%s: vreg set level failed (%d)\n",
- __func__, rc);
- goto vreg_set_level_fail;
+ rc = on ? regulator_set_voltage(bt_vregs[i].reg,
+ bt_vregs[i].min_level,
+ bt_vregs[i].max_level) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not set voltage for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_disable;
}
- if (bt_vregs[i].is_pin_controlled == 1) {
- rc = pmapp_vreg_pincntrl_vote(id,
- bt_vregs[i].pmapp_id,
+
+ rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not %sable regulator %s: %d\n",
+ __func__, "en", bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+
+ if (bt_vregs[i].is_pin_controlled) {
+ rc = pmapp_vreg_lpm_pincntrl_vote(id,
+ bt_vregs[i].pmapp_id,
PMAPP_CLOCK_ID_D1,
on ? PMAPP_CLOCK_VOTE_ON :
- PMAPP_CLOCK_VOTE_OFF);
- } else {
- rc = on ? vreg_enable(bt_vregs[i].vregs) :
- vreg_disable(bt_vregs[i].vregs);
+ PMAPP_CLOCK_VOTE_OFF);
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: pin control failed for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto pin_cnt_fail;
+ }
}
+ rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
- if (rc < 0) {
- pr_err("%s: vreg %s %s failed(%d)\n",
- __func__, bt_vregs[i].name,
- on ? "enable" : "disable", rc);
- goto vreg_fail;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not %sable regulator %s: %d\n",
+ __func__, "dis", bt_vregs[i].name, rc);
+ goto reg_disable;
}
}
return rc;
-
-vreg_fail:
+pin_cnt_fail:
+ if (on)
+ regulator_disable(bt_vregs[i].reg);
+reg_disable:
while (i) {
- if (on)
- vreg_disable(bt_vregs[--i].vregs);
+ if (on) {
+ i--;
+ regulator_disable(bt_vregs[i].reg);
+ regulator_put(bt_vregs[i].reg);
}
-vreg_set_level_fail:
- vreg_put(bt_vregs[0].vregs);
- vreg_put(bt_vregs[1].vregs);
+ }
return rc;
}
+static struct regulator *reg_s3;
static unsigned int msm_bahama_setup_power(void)
{
int rc = 0;
- struct vreg *vreg_s3 = NULL;
- vreg_s3 = vreg_get(NULL, "msme1");
- if (IS_ERR(vreg_s3)) {
- pr_err("%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_s3));
- return PTR_ERR(vreg_s3);
+ reg_s3 = regulator_get(NULL, "msme1");
+ if (IS_ERR(reg_s3)) {
+ rc = PTR_ERR(reg_s3);
+ pr_err("%s: could not get regulator: %d\n", __func__, rc);
+ goto out;
}
- rc = vreg_set_level(vreg_s3, 1800);
+
+ rc = regulator_set_voltage(reg_s3, 1800000, 1800000);
if (rc < 0) {
- pr_err("%s: vreg set level failed (%d)\n",
- __func__, rc);
- goto vreg_fail;
+ pr_err("%s: could not set voltage: %d\n", __func__, rc);
+ goto reg_fail;
}
- rc = vreg_enable(vreg_s3);
+
+ rc = regulator_enable(reg_s3);
if (rc < 0) {
- pr_err("%s: vreg enable failed (%d)\n",
- __func__, rc);
- goto vreg_fail;
+ pr_err("%s: could not enable regulator: %d\n", __func__, rc);
+ goto reg_fail;
}
/*setup Bahama_sys_reset_n*/
@@ -661,48 +680,62 @@
if (rc < 0) {
pr_err("%s: gpio_request %d = %d\n", __func__,
GPIO_BT_SYS_REST_EN, rc);
- goto vreg_fail;
+ goto reg_disable;
}
+
rc = bt_set_gpio(1);
if (rc < 0) {
pr_err("%s: bt_set_gpio %d = %d\n", __func__,
GPIO_BT_SYS_REST_EN, rc);
goto gpio_fail;
}
+
return rc;
gpio_fail:
gpio_free(GPIO_BT_SYS_REST_EN);
-vreg_fail:
- vreg_put(vreg_s3);
+reg_disable:
+ regulator_disable(reg_s3);
+reg_fail:
+ regulator_put(reg_s3);
+out:
+ reg_s3 = NULL;
return rc;
}
static unsigned int msm_bahama_shutdown_power(int value)
{
int rc = 0;
- struct vreg *vreg_s3 = NULL;
- vreg_s3 = vreg_get(NULL, "msme1");
- if (IS_ERR(vreg_s3)) {
- pr_err("%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_s3));
- return PTR_ERR(vreg_s3);
+ if (IS_ERR_OR_NULL(reg_s3)) {
+ rc = reg_s3 ? PTR_ERR(reg_s3) : -ENODEV;
+ goto out;
}
- rc = vreg_disable(vreg_s3);
+
+ rc = regulator_disable(reg_s3);
if (rc) {
- pr_err("%s: vreg disable failed (%d)\n",
- __func__, rc);
- vreg_put(vreg_s3);
- return rc;
+ pr_err("%s: could not disable regulator: %d\n", __func__, rc);
+ goto out;
}
+
if (value == BAHAMA_ID) {
rc = bt_set_gpio(0);
if (rc) {
pr_err("%s: bt_set_gpio = %d\n",
__func__, rc);
+ goto reg_enable;
}
+ gpio_free(GPIO_BT_SYS_REST_EN);
}
+
+ regulator_put(reg_s3);
+ reg_s3 = NULL;
+
+ return 0;
+
+reg_enable:
+ regulator_enable(reg_s3);
+out:
return rc;
}
@@ -863,25 +896,27 @@
static int __init bt_power_init(void)
{
int i, rc = 0;
- for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
- bt_vregs[i].vregs = vreg_get(NULL,
- bt_vregs[i].name);
- if (IS_ERR(bt_vregs[i].vregs)) {
- pr_err("%s: vreg get %s failed (%ld)\n",
- __func__, bt_vregs[i].name,
- PTR_ERR(bt_vregs[i].vregs));
- rc = PTR_ERR(bt_vregs[i].vregs);
- goto vreg_get_fail;
- }
- }
+ struct device *dev = &msm_bt_power_device.dev;
- msm_bt_power_device.dev.platform_data = &bluetooth_power;
+ for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+ bt_vregs[i].reg = regulator_get(dev, bt_vregs[i].name);
+ if (IS_ERR(bt_vregs[i].reg)) {
+ rc = PTR_ERR(bt_vregs[i].reg);
+ dev_err(dev, "%s: could not get regulator %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_get_fail;
+ }
+ }
+
+ dev->platform_data = &bluetooth_power;
return rc;
-vreg_get_fail:
- while (i)
- vreg_put(bt_vregs[--i].vregs);
+reg_get_fail:
+ while (i--) {
+ regulator_put(bt_vregs[i].reg);
+ bt_vregs[i].reg = NULL;
+ }
return rc;
}
@@ -1144,35 +1179,52 @@
return msm_hsusb_rpc_close();
}
-static struct vreg *vreg_3p3;
+static struct regulator *reg_hsusb;
static int msm_hsusb_ldo_init(int init)
{
- if (init) {
- vreg_3p3 = vreg_get(NULL, "usb");
- if (IS_ERR(vreg_3p3))
- return PTR_ERR(vreg_3p3);
- } else
- vreg_put(vreg_3p3);
+ int rc = 0;
- return 0;
+ if (init) {
+ reg_hsusb = regulator_get(NULL, "usb");
+ if (IS_ERR(reg_hsusb)) {
+ rc = PTR_ERR(reg_hsusb);
+ pr_err("%s: could not get regulator: %d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ rc = regulator_set_voltage(reg_hsusb, 3300000, 3300000);
+ if (rc) {
+ pr_err("%s: could not set voltage: %d\n",
+ __func__, rc);
+ goto reg_free;
+ }
+
+ return 0;
+ }
+ /* else fall through */
+reg_free:
+ regulator_put(reg_hsusb);
+out:
+ reg_hsusb = NULL;
+ return rc;
}
static int msm_hsusb_ldo_enable(int enable)
{
static int ldo_status;
- if (!vreg_3p3 || IS_ERR(vreg_3p3))
- return -ENODEV;
+ if (IS_ERR_OR_NULL(reg_hsusb))
+ return reg_hsusb ? PTR_ERR(reg_hsusb) : -ENODEV;
if (ldo_status == enable)
return 0;
ldo_status = enable;
- if (enable)
- return vreg_enable(vreg_3p3);
-
- return vreg_disable(vreg_3p3);
+ return enable ?
+ regulator_enable(reg_hsusb) :
+ regulator_disable(reg_hsusb);
}
#ifndef CONFIG_USB_EHCI_MSM_72K
@@ -1219,15 +1271,6 @@
|| defined(CONFIG_MMC_MSM_SDC4_SUPPORT))
static unsigned long vreg_sts, gpio_sts;
-static struct vreg *vreg_mmc;
-static struct vreg *vreg_emmc;
-
-struct sdcc_vreg {
- struct vreg *vreg_data;
- unsigned level;
-};
-
-static struct sdcc_vreg sdcc_vreg_data[4];
struct sdcc_gpio {
struct msm_gpio *cfg_data;
@@ -1346,6 +1389,7 @@
},
};
+static struct regulator *sdcc_vreg_data[ARRAY_SIZE(sdcc_cfg_data)];
static int msm_sdcc_setup_gpio(int dev_id, unsigned int enable)
{
int rc = 0;
@@ -1376,27 +1420,31 @@
static int msm_sdcc_setup_vreg(int dev_id, unsigned int enable)
{
int rc = 0;
- struct sdcc_vreg *curr;
+ struct regulator *curr = sdcc_vreg_data[dev_id - 1];
- curr = &sdcc_vreg_data[dev_id - 1];
+ if (test_bit(dev_id, &vreg_sts) == enable)
+ return 0;
- if (!(test_bit(dev_id, &vreg_sts)^enable))
- return rc;
+ if (!curr)
+ return -ENODEV;
+
+ if (IS_ERR(curr))
+ return PTR_ERR(curr);
if (enable) {
set_bit(dev_id, &vreg_sts);
- rc = vreg_set_level(curr->vreg_data, curr->level);
- if (rc)
- pr_err("%s: vreg_set_level() = %d\n", __func__, rc);
- rc = vreg_enable(curr->vreg_data);
+ rc = regulator_enable(curr);
if (rc)
- pr_err("%s: vreg_enable() = %d\n", __func__, rc);
+ pr_err("%s: could not enable regulator: %d\n",
+ __func__, rc);
} else {
clear_bit(dev_id, &vreg_sts);
- rc = vreg_disable(curr->vreg_data);
+
+ rc = regulator_disable(curr);
if (rc)
- pr_err("%s: vreg_disable() = %d\n", __func__, rc);
+ pr_err("%s: could not disable regulator: %d\n",
+ __func__, rc);
}
return rc;
}
@@ -1644,45 +1692,65 @@
}
};
+static int __init mmc_regulator_init(int sdcc_no, const char *supply, int uV)
+{
+ int rc;
+
+ BUG_ON(sdcc_no < 1 || sdcc_no > 4);
+
+ sdcc_no--;
+
+ sdcc_vreg_data[sdcc_no] = regulator_get(NULL, supply);
+
+ if (IS_ERR(sdcc_vreg_data[sdcc_no])) {
+ rc = PTR_ERR(sdcc_vreg_data[sdcc_no]);
+ pr_err("%s: could not get regulator \"%s\": %d\n",
+ __func__, supply, rc);
+ goto out;
+ }
+
+ rc = regulator_set_voltage(sdcc_vreg_data[sdcc_no], uV, uV);
+
+ if (rc) {
+ pr_err("%s: could not set voltage for \"%s\" to %d uV: %d\n",
+ __func__, supply, uV, rc);
+ goto reg_free;
+ }
+
+ return rc;
+
+reg_free:
+ regulator_put(sdcc_vreg_data[sdcc_no]);
+out:
+ sdcc_vreg_data[sdcc_no] = NULL;
+ return rc;
+}
+
static void __init msm7627a_init_mmc(void)
{
- vreg_emmc = vreg_get(NULL, "emmc");
- if (IS_ERR(vreg_emmc)) {
- pr_err("%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_emmc));
- return;
- }
-
- vreg_mmc = vreg_get(NULL, "mmc");
- if (IS_ERR(vreg_mmc)) {
- pr_err("%s: vreg get failed (%ld)\n",
- __func__, PTR_ERR(vreg_mmc));
- return;
- }
-
/* eMMC slot */
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- sdcc_vreg_data[2].vreg_data = vreg_emmc;
- sdcc_vreg_data[2].level = 3000;
+ if (mmc_regulator_init(3, "emmc", 3000000))
+ return;
msm_add_sdcc(3, &sdc3_plat_data);
#endif
/* Micro-SD slot */
#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
- sdcc_vreg_data[0].vreg_data = vreg_mmc;
- sdcc_vreg_data[0].level = 2850;
+ if (mmc_regulator_init(1, "mmc", 2850000))
+ return;
msm_add_sdcc(1, &sdc1_plat_data);
#endif
/* SDIO WLAN slot */
#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
- sdcc_vreg_data[1].vreg_data = vreg_mmc;
- sdcc_vreg_data[1].level = 2850;
+ if (mmc_regulator_init(2, "mmc", 2850000))
+ return;
msm_add_sdcc(2, &sdc2_plat_data);
#endif
/* Not Used */
#if (defined(CONFIG_MMC_MSM_SDC4_SUPPORT)\
&& !defined(CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT))
- sdcc_vreg_data[3].vreg_data = vreg_mmc;
- sdcc_vreg_data[3].level = 2850;
+ if (mmc_regulator_init(4, "mmc", 2850000))
+ return;
msm_add_sdcc(4, &sdc4_plat_data);
#endif
}
@@ -1945,98 +2013,39 @@
}
#endif
-static struct vreg *vreg_gp1;
-static struct vreg *vreg_gp2;
-static struct vreg *vreg_gp3;
-static void msm_camera_vreg_config(int vreg_en)
+static struct regulator_bulk_data regs_camera[] = {
+ { .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
+ { .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
+ { .supply = "usb2", .min_uV = 1800000, .max_uV = 1800000 },
+};
+
+static void __init msm_camera_vreg_init(void)
{
int rc;
- if (vreg_gp1 == NULL) {
- vreg_gp1 = vreg_get(NULL, "msme1");
- if (IS_ERR(vreg_gp1)) {
- pr_err("%s: vreg_get(%s) failed (%ld)\n",
- __func__, "msme1", PTR_ERR(vreg_gp1));
- return;
- }
-
- rc = vreg_set_level(vreg_gp1, 1800);
- if (rc) {
- pr_err("%s: GP1 set_level failed (%d)\n",
- __func__, rc);
- return;
- }
+ rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
+ if (rc) {
+ pr_err("%s: could not get regulators: %d\n", __func__, rc);
+ return;
}
- if (vreg_gp2 == NULL) {
- vreg_gp2 = vreg_get(NULL, "gp2");
- if (IS_ERR(vreg_gp2)) {
- pr_err("%s: vreg_get(%s) failed (%ld)\n",
- __func__, "gp2", PTR_ERR(vreg_gp2));
- return;
- }
-
- rc = vreg_set_level(vreg_gp2, 2850);
- if (rc) {
- pr_err("%s: GP2 set_level failed (%d)\n",
- __func__, rc);
- }
- }
-
- if (vreg_gp3 == NULL) {
- vreg_gp3 = vreg_get(NULL, "usb2");
- if (IS_ERR(vreg_gp3)) {
- pr_err("%s: vreg_get(%s) failed (%ld)\n",
- __func__, "gp3", PTR_ERR(vreg_gp3));
- return;
- }
-
- rc = vreg_set_level(vreg_gp3, 1800);
- if (rc) {
- pr_err("%s: GP3 set level failed (%d)\n",
- __func__, rc);
- }
- }
-
- if (vreg_en) {
- rc = vreg_enable(vreg_gp1);
- if (rc) {
- pr_err("%s: GP1 enable failed (%d)\n",
- __func__, rc);
- return;
- }
-
- rc = vreg_enable(vreg_gp2);
- if (rc) {
- pr_err("%s: GP2 enable failed (%d)\n",
- __func__, rc);
- }
-
- rc = vreg_enable(vreg_gp3);
- if (rc) {
- pr_err("%s: GP3 enable failed (%d)\n",
- __func__, rc);
- }
- } else {
- rc = vreg_disable(vreg_gp1);
- if (rc)
- pr_err("%s: GP1 disable failed (%d)\n",
- __func__, rc);
-
- rc = vreg_disable(vreg_gp2);
- if (rc) {
- pr_err("%s: GP2 disable failed (%d)\n",
- __func__, rc);
- }
-
- rc = vreg_disable(vreg_gp3);
- if (rc) {
- pr_err("%s: GP3 disable failed (%d)\n",
- __func__, rc);
- }
+ rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_camera), regs_camera);
+ if (rc) {
+ pr_err("%s: could not set voltages: %d\n", __func__, rc);
+ return;
}
}
+static void msm_camera_vreg_config(int vreg_en)
+{
+ int rc = vreg_en ?
+ regulator_bulk_enable(ARRAY_SIZE(regs_camera), regs_camera) :
+ regulator_bulk_disable(ARRAY_SIZE(regs_camera), regs_camera);
+
+ if (rc)
+ pr_err("%s: could not %sable regulators: %d\n",
+ __func__, vreg_en ? "en" : "dis", rc);
+}
static int config_gpio_table(uint32_t *table, int len)
{
int rc = 0, i = 0;
@@ -2563,6 +2572,7 @@
bt_power_init();
#endif
+ msm_camera_vreg_init();
i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID, i2c_camera_devices,
ARRAY_SIZE(i2c_camera_devices));
diff --git a/arch/arm/mach-msm/board-sapphire-keypad.c b/arch/arm/mach-msm/board-sapphire-keypad.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/board-sapphire-mmc.c b/arch/arm/mach-msm/board-sapphire-mmc.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 8f57f88..40e13fa 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -93,6 +93,7 @@
ldr r0, [r0]
mov r1, #0
mcr p15, 2, r1, c0, c0, 0 /*CCSELR*/
+ isb
mrc p15, 1, r1, c0, c0, 0 /*CCSIDR*/
mov r2, #1
and r1, r2, r1, ASR #30 /* Check if the cache is write back */
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index 6becc61..bcc4c64 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index b1d2ee8..492fa0e 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -82,7 +82,8 @@
unsigned long subframe_pkt_addr;
unsigned long subframe_pkt_size;
unsigned short *frame_header_pkt;
- int i, num_addr, skip, start_pos = 0, xdim_pos = 1, ydim_pos = 2;
+ int i, num_addr, col_addr = 0, skip;
+ int start_pos = 0, xdim_pos = 1, ydim_pos = 2;
unsigned short *frame_buffer_high, *frame_buffer_low;
unsigned long frame_buffer_size;
unsigned short frame_buffer_size_high, frame_buffer_size_low;
@@ -133,9 +134,10 @@
skip = 0;
start_pos = 5;
} else {
- num_addr = 33;
+ num_addr = 16;
skip = 0;
start_pos = 6;
+ col_addr = 17;
}
break;
case 0x8201: /* h.264 vld in arm */
@@ -216,6 +218,29 @@
NULL, NULL, NULL, NULL))
return -EINVAL;
}
+ if (col_addr) {
+ frame_buffer_high += 2;
+ frame_buffer_low += 2;
+ /* Patch the Co-located buffers.*/
+ frame_buffer_size = (72 * frame_header_pkt[xdim_pos] *
+ frame_header_pkt[ydim_pos]) >> 16;
+ ptr_to_high_low_short((void *)frame_buffer_size,
+ &frame_buffer_size_high,
+ &frame_buffer_size_low);
+ for (i = 0; i < col_addr; i++) {
+ if (frame_buffer_high && frame_buffer_low) {
+ if (pmem_fixup_high_low(frame_buffer_high,
+ frame_buffer_low,
+ frame_buffer_size_high,
+ frame_buffer_size_low,
+ module,
+ NULL, NULL, NULL, NULL))
+ return -EINVAL;
+ }
+ frame_buffer_high += 2;
+ frame_buffer_low += 2;
+ }
+ }
/*Flush the cached pmem subframe packet before sending to DSP*/
if (filp) {
pmem_addr.vaddr = subframe_pkt_addr;
diff --git a/arch/arm/mach-msm/qdsp5v2/Makefile b/arch/arm/mach-msm/qdsp5v2/Makefile
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index b9086e3..dc6ba5c 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -567,8 +567,6 @@
* Only register the platform driver for targets older than that.
*/
if (cpu_is_msm7x01() || cpu_is_msm7x25() || cpu_is_msm7x27() ||
- cpu_is_msm7x27a() || cpu_is_msm7x27aa() ||
- cpu_is_msm7x25a() || cpu_is_msm7x25aa() ||
cpu_is_msm7x30() || cpu_is_qsd8x50() ||
cpu_is_msm8x55() || (cpu_is_msm8x60() &&
socinfo_get_platform_subtype() == 0x1)) {
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 9beef12..84a7e5c 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -796,14 +796,9 @@
int i, j, highmem = 0;
#if (defined CONFIG_HIGHMEM) && (defined CONFIG_FIX_MOVABLE_ZONE)
-
-/* For now, we must ensure that a small highmem zone exists
- * after most of it is transformed into the movable zone.
- */
-#define MIN_HIGHMEM_SIZE (5 * SECTION_SIZE)
void *v_movable_start;
- v_movable_start = __va(movable_reserved_start) - MIN_HIGHMEM_SIZE;
+ v_movable_start = __va(movable_reserved_start);
if (vmalloc_min > v_movable_start)
vmalloc_min = v_movable_start;
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 6003846..5acf23d 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1322,6 +1322,7 @@
struct adreno_context *context)
{
struct kgsl_device *device = &adreno_dev->dev;
+ unsigned int cmd[22];
if (context == NULL)
return;
@@ -1363,6 +1364,30 @@
context->chicken_restore, 3);
context->flags |= CTXT_FLAGS_GMEM_RESTORE;
+ } else if (adreno_is_a225(adreno_dev)) {
+ unsigned int *cmds = &cmd[0];
+ /*
+ * Issue an empty draw call to avoid possible hangs due to
+ * repeated idles without intervening draw calls.
+ * On adreno 225 the PC block has a cache that is only
+ * flushed on draw calls and repeated idles can make it
+ * overflow. The gmem save path contains draw calls so
+ * this workaround isn't needed there.
+ */
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
+ *cmds++ = 0;
+ *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
+ *cmds++ = 0;
+ *cmds++ = 1<<14;
+ *cmds++ = 0;
+ *cmds++ = device->mmu.setstate_memory.gpuaddr;
+ *cmds++ = 0;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+ adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+ &cmd[0], 11);
}
}
diff --git a/drivers/input/touchscreen/cyttsp_fw.h b/drivers/input/touchscreen/cyttsp_fw.h
old mode 100755
new mode 100644
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 2d42e17..e4430ad 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -2676,6 +2676,14 @@
FMDERR("Failed to set stereo mode\n");
return retval;
}
+ radio->event_mask = SIG_LEVEL_INTR |
+ RDS_SYNC_INTR | AUDIO_CTRL_INTR;
+ retval = hci_conf_event_mask(&radio->event_mask,
+ radio->fm_hdev);
+ if (retval < 0) {
+ FMDERR("Enable Async events failed");
+ return retval;
+ }
retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
radio->fm_hdev);
if (retval < 0)
diff --git a/drivers/media/video/msm/msm_io_vfe31.c b/drivers/media/video/msm/msm_io_vfe31.c
index 1cd731c..f770ce9 100644
--- a/drivers/media/video/msm/msm_io_vfe31.c
+++ b/drivers/media/video/msm/msm_io_vfe31.c
@@ -111,11 +111,6 @@
static struct clk *camio_jpeg_clk;
static struct clk *camio_jpeg_pclk;
static struct clk *camio_vpe_clk;
-static struct vreg *vreg_gp2;
-static struct vreg *vreg_lvsw1;
-static struct vreg *vreg_gp6;
-static struct vreg *vreg_gp16;
-static struct regulator *fs_vfe;
static struct regulator *fs_vpe;
static struct msm_camera_io_ext camio_ext;
static struct msm_camera_io_clk camio_clk;
@@ -123,6 +118,17 @@
void __iomem *camifpadbase, *csibase;
static uint32_t vpe_clk_rate;
+static struct regulator_bulk_data regs[] = {
+ { .supply = "gp2", .min_uV = 2600000, .max_uV = 2600000 },
+ { .supply = "lvsw1" },
+ { .supply = "fs_vfe" },
+ /* sn12m0pz regulators */
+ { .supply = "gp6", .min_uV = 3050000, .max_uV = 3100000 },
+ { .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+};
+
+static int reg_count;
+
void msm_io_w(u32 data, void __iomem *addr)
{
CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
@@ -201,135 +207,54 @@
static void msm_camera_vreg_enable(struct platform_device *pdev)
{
- vreg_gp2 = vreg_get(NULL, "gp2");
- if (IS_ERR(vreg_gp2)) {
- pr_err("%s: VREG GP2 get failed %ld\n", __func__,
- PTR_ERR(vreg_gp2));
- vreg_gp2 = NULL;
+ int count, rc;
+
+ struct device *dev = &pdev->dev;
+
+ /* Use gp6 and gp16 if and only if dev name matches. */
+ if (!strncmp(pdev->name, "msm_camera_sn12m0pz", 20))
+ count = ARRAY_SIZE(regs);
+ else
+ count = ARRAY_SIZE(regs) - 2;
+
+ rc = regulator_bulk_get(dev, count, regs);
+
+ if (rc) {
+ dev_err(dev, "%s: could not get regulators: %d\n",
+ __func__, rc);
return;
}
- if (vreg_set_level(vreg_gp2, 2600)) {
- pr_err("%s: VREG GP2 set failed\n", __func__);
- goto gp2_put;
+ rc = regulator_bulk_set_voltage(count, regs);
+
+ if (rc) {
+ dev_err(dev, "%s: could not set voltages: %d\n",
+ __func__, rc);
+ goto reg_free;
}
- if (vreg_enable(vreg_gp2)) {
- pr_err("%s: VREG GP2 enable failed\n", __func__);
- goto gp2_put;
+ rc = regulator_bulk_enable(count, regs);
+
+ if (rc) {
+ dev_err(dev, "%s: could not enable regulators: %d\n",
+ __func__, rc);
+ goto reg_free;
}
- vreg_lvsw1 = vreg_get(NULL, "lvsw1");
- if (IS_ERR(vreg_lvsw1)) {
- pr_err("%s: VREG LVSW1 get failed %ld\n", __func__,
- PTR_ERR(vreg_lvsw1));
- vreg_lvsw1 = NULL;
- goto gp2_disable;
- }
- if (vreg_set_level(vreg_lvsw1, 1800)) {
- pr_err("%s: VREG LVSW1 set failed\n", __func__);
- goto lvsw1_put;
- }
- if (vreg_enable(vreg_lvsw1)) {
- pr_err("%s: VREG LVSW1 enable failed\n", __func__);
- goto lvsw1_put;
- }
-
- if (!strcmp(pdev->name, "msm_camera_sn12m0pz")) {
- vreg_gp6 = vreg_get(NULL, "gp6");
- if (IS_ERR(vreg_gp6)) {
- pr_err("%s: VREG GP6 get failed %ld\n", __func__,
- PTR_ERR(vreg_gp6));
- vreg_gp6 = NULL;
- goto lvsw1_disable;
- }
-
- if (vreg_set_level(vreg_gp6, 3050)) {
- pr_err("%s: VREG GP6 set failed\n", __func__);
- goto gp6_put;
- }
-
- if (vreg_enable(vreg_gp6)) {
- pr_err("%s: VREG GP6 enable failed\n", __func__);
- goto gp6_put;
- }
- vreg_gp16 = vreg_get(NULL, "gp16");
- if (IS_ERR(vreg_gp16)) {
- pr_err("%s: VREG GP16 get failed %ld\n", __func__,
- PTR_ERR(vreg_gp16));
- vreg_gp16 = NULL;
- goto gp6_disable;
- }
-
- if (vreg_set_level(vreg_gp16, 1200)) {
- pr_err("%s: VREG GP16 set failed\n", __func__);
- goto gp16_put;
- }
-
- if (vreg_enable(vreg_gp16)) {
- pr_err("%s: VREG GP16 enable failed\n", __func__);
- goto gp16_put;
- }
- }
-
- fs_vfe = regulator_get(NULL, "fs_vfe");
- if (IS_ERR(fs_vfe)) {
- pr_err("%s: Regulator FS_VFE get failed %ld\n", __func__,
- PTR_ERR(fs_vfe));
- fs_vfe = NULL;
- } else if (regulator_enable(fs_vfe)) {
- pr_err("%s: Regulator FS_VFE enable failed\n", __func__);
- regulator_put(fs_vfe);
- }
-
+ reg_count = count;
return;
-gp16_put:
- vreg_put(vreg_gp16);
- vreg_gp16 = NULL;
-gp6_disable:
- vreg_disable(vreg_gp6);
-gp6_put:
- vreg_put(vreg_gp6);
- vreg_gp6 = NULL;
-lvsw1_disable:
- vreg_disable(vreg_lvsw1);
-lvsw1_put:
- vreg_put(vreg_lvsw1);
- vreg_lvsw1 = NULL;
-gp2_disable:
- vreg_disable(vreg_gp2);
-gp2_put:
- vreg_put(vreg_gp2);
- vreg_gp2 = NULL;
+reg_free:
+ regulator_bulk_free(count, regs);
+ return;
}
+
static void msm_camera_vreg_disable(void)
{
- if (vreg_gp2) {
- vreg_disable(vreg_gp2);
- vreg_put(vreg_gp2);
- vreg_gp2 = NULL;
- }
- if (vreg_lvsw1) {
- vreg_disable(vreg_lvsw1);
- vreg_put(vreg_lvsw1);
- vreg_lvsw1 = NULL;
- }
- if (vreg_gp6) {
- vreg_disable(vreg_gp6);
- vreg_put(vreg_gp6);
- vreg_gp6 = NULL;
- }
- if (vreg_gp16) {
- vreg_disable(vreg_gp16);
- vreg_put(vreg_gp16);
- vreg_gp16 = NULL;
- }
- if (fs_vfe) {
- regulator_disable(fs_vfe);
- regulator_put(fs_vfe);
- }
+ regulator_bulk_disable(reg_count, regs);
+ regulator_bulk_free(reg_count, regs);
+ reg_count = 0;
}
int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
old mode 100755
new mode 100644
diff --git a/drivers/platform/msm/sps/Makefile b/drivers/platform/msm/sps/Makefile
old mode 100755
new mode 100644
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 552ed82..d7a7b5a 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1688,13 +1688,31 @@
power_supply_changed(&chip->dc_psy);
return IRQ_HANDLED;
}
-
+/*
+ *
+ * bat_temp_ok_irq_handler - is edge triggered, hence it will
+ * fire for two cases:
+ *
+ * If the interrupt line switches to high temperature is okay
+ * and thus charging begins.
+ * If bat_temp_ok is low this means the temperature is now
+ * too hot or cold, so charging is stopped.
+ *
+ */
static irqreturn_t bat_temp_ok_irq_handler(int irq, void *data)
{
+ int bat_temp_ok;
struct pm8921_chg_chip *chip = data;
- pr_debug("batt temp ok fsm_state=%d\n", pm_chg_get_fsm_state(data));
- handle_start_ext_chg(chip);
+ bat_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
+
+ pr_debug("batt_temp_ok = %d fsm_state%d\n",
+ bat_temp_ok, pm_chg_get_fsm_state(data));
+
+ if (bat_temp_ok)
+ handle_start_ext_chg(chip);
+ else
+ handle_stop_ext_chg(chip);
power_supply_changed(&chip->batt_psy);
power_supply_changed(&chip->usb_psy);
@@ -2119,6 +2137,7 @@
pm8921_chg_enable_irq(chip, CHGFAIL_IRQ);
pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
+ pm8921_chg_enable_irq(chip, BAT_TEMP_OK_IRQ);
spin_lock_irqsave(&vbus_lock, flags);
if (usb_chg_current) {
diff --git a/drivers/staging/gobi/QCUSBNet2k/Makefile b/drivers/staging/gobi/QCUSBNet2k/Makefile
old mode 100755
new mode 100644
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index bc1a25b..a834128 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -1999,12 +1999,12 @@
tasklet_kill(&msm_uport->rx.tlet);
cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
- spin_lock_irqsave(&uport->lock, flags);
clk_enable(msm_uport->clk);
pm_runtime_disable(uport->dev);
pm_runtime_set_suspended(uport->dev);
+ spin_lock_irqsave(&uport->lock, flags);
/* Disable the transmitter */
msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK);
/* Disable the receiver */
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 2bfd914..56bf2b5 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -609,26 +609,14 @@
static int rndis_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
{
- int ret;
- struct rndis_function_config *rndis;
-
f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
if (!f->config)
return -ENOMEM;
-
- rndis = f->config;
- ret = gether_setup_name(cdev->gadget, rndis->ethaddr, "usb");
- if (ret) {
- pr_err("%s: gether_setup failed\n", __func__);
- return ret;
- }
-
return 0;
}
static void rndis_function_cleanup(struct android_usb_function *f)
{
- gether_cleanup();
kfree(f->config);
f->config = NULL;
}
@@ -636,6 +624,7 @@
static int rndis_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
+ int ret;
struct rndis_function_config *rndis = f->config;
if (!rndis) {
@@ -647,6 +636,12 @@
rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
+ ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
+ if (ret) {
+ pr_err("%s: gether_setup failed\n", __func__);
+ return ret;
+ }
+
if (rndis->wceis) {
/* "Wireless" RNDIS; auto-detected by Windows */
rndis_iad_descriptor.bFunctionClass =
@@ -666,6 +661,7 @@
static void rndis_function_unbind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
+ gether_cleanup();
}
static ssize_t rndis_manufacturer_show(struct device *dev,
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 11bfe9f..17fe820 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2862,6 +2862,7 @@
udc->softconnect = 1;
spin_unlock_irqrestore(udc->lock, flags);
+ pm_runtime_get_sync(&udc->gadget.dev);
retval = bind(&udc->gadget); /* MAY SLEEP */
spin_lock_irqsave(udc->lock, flags);
@@ -2871,13 +2872,11 @@
}
udc->driver = driver;
- pm_runtime_get_sync(&udc->gadget.dev);
if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
if (udc->vbus_active) {
if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
hw_device_reset(udc);
} else {
- pm_runtime_put_sync(&udc->gadget.dev);
goto done;
}
}
@@ -2886,11 +2885,11 @@
goto done;
retval = hw_device_state(udc->ep0out.qh.dma);
- if (retval)
- pm_runtime_put_sync(&udc->gadget.dev);
done:
spin_unlock_irqrestore(udc->lock, flags);
+ if (retval)
+ pm_runtime_put_sync(&udc->gadget.dev);
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
diff --git a/drivers/usb/host/pehci/host/otg.c b/drivers/usb/host/pehci/host/otg.c
old mode 100755
new mode 100644
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 07d7789..e11339c 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -49,6 +49,8 @@
#define MSM_HDMI_SAMPLE_RATE_MAX 7
#define MSM_HDMI_SAMPLE_RATE_FORCE_32BIT 0x7FFFFFFF
+static int msm_hdmi_sample_rate = MSM_HDMI_SAMPLE_RATE_48KHZ;
+
struct workqueue_struct *hdmi_work_queue;
struct hdmi_msm_state_type *hdmi_msm_state;
@@ -3331,6 +3333,19 @@
}
#endif
+int hdmi_msm_audio_get_sample_rate(void)
+{
+ return msm_hdmi_sample_rate;
+}
+EXPORT_SYMBOL(hdmi_msm_audio_get_sample_rate);
+
+void hdmi_msm_audio_sample_rate_reset(int rate)
+{
+ msm_hdmi_sample_rate = rate;
+ hdcp_deauthenticate();
+}
+EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset);
+
static void hdmi_msm_audio_setup(void)
{
const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
@@ -3344,7 +3359,7 @@
DEV_DBG("Not setting ACP, ISRC1, ISRC2 packets\n");
hdmi_msm_audio_acr_setup(TRUE,
external_common_state->video_resolution,
- MSM_HDMI_SAMPLE_RATE_48KHZ, channels);
+ msm_hdmi_sample_rate, channels);
hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
/* Turn on Audio FIFO and SAM DROP ISR */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index a511e3c..2eb08b8 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -320,16 +320,29 @@
ulong intr_dma_e;
ulong intr_overlay0;
ulong intr_overlay1;
+ ulong intr_vsync_p; /* Primary interface */
ulong intr_underrun_p; /* Primary interface */
+ ulong intr_vsync_e; /* external interface */
ulong intr_underrun_e; /* external interface */
+ ulong intr_histogram;
+ ulong intr_rd_ptr;
+ ulong dsi_mdp_start;
+ ulong dsi_clk_on;
+ ulong dsi_clk_off;
ulong intr_dsi;
- ulong kickoff_mddi;
- ulong kickoff_lcdc;
- ulong kickoff_dtv;
- ulong kickoff_atv;
- ulong kickoff_dsi;
- ulong kickoff_writeback;
- ulong writeback; /* blt */
+ ulong intr_dsi_mdp;
+ ulong intr_dsi_cmd;
+ ulong intr_dsi_err;
+ ulong kickoff_ov0;
+ ulong kickoff_ov1;
+ ulong kickoff_dmap;
+ ulong kickoff_dmae;
+ ulong kickoff_dmas;
+ ulong blt_dsi_cmd; /* blt */
+ ulong blt_dsi_video; /* blt */
+ ulong blt_lcdc; /* blt */
+ ulong blt_dtv; /* blt */
+ ulong blt_mddi; /* blt */
ulong overlay_set[MDP4_MIXER_MAX];
ulong overlay_unset[MDP4_MIXER_MAX];
ulong overlay_play[MDP4_MIXER_MAX];
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 770424a..aecf554 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -65,7 +65,6 @@
{
if (mipi_dsi_clk_on) {
if (dsi_state == ST_DSI_PLAYING) {
- mdp4_stat.dsi_clkoff++;
mipi_dsi_turn_off_clks();
mdp4_overlay_dsi_state_set(ST_DSI_CLK_OFF);
}
@@ -325,7 +324,7 @@
dsi_pipe->ov_cnt = 0;
dsi_pipe->dmap_cnt = 0;
dsi_pipe->blt_addr = dsi_pipe->blt_base;
- mdp4_stat.writeback++;
+ mdp4_stat.blt_dsi_cmd++;
spin_unlock_irqrestore(&mdp_spin_lock, flag);
return 0;
}
@@ -465,6 +464,7 @@
mdp4_blt_xy_update(dsi_pipe);
/* kick off dmap */
outpdw(MDP_BASE + 0x000c, 0x0);
+ mdp4_stat.kickoff_dmap++;
/* trigger dsi cmd engine */
mipi_dsi_cmd_mdp_start();
@@ -525,6 +525,7 @@
mdp_enable_irq(MDP_DMA2_TERM); /* enable intr */
/* kick off dmap */
outpdw(MDP_BASE + 0x000c, 0x0);
+ mdp4_stat.kickoff_dmap++;
/* trigger dsi cmd engine */
mipi_dsi_cmd_mdp_start();
mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
@@ -670,6 +671,7 @@
/* start OVERLAY pipe */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+ mdp4_stat.kickoff_ov0++;
}
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)
@@ -686,9 +688,6 @@
mdp4_dsi_cmd_kickoff_ui(mfd, dsi_pipe);
-
- mdp4_stat.kickoff_dsi++;
-
/* signal if pan function is waiting for the update completion */
if (mfd->pan_waiting) {
mfd->pan_waiting = FALSE;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 1a5cb65..63beb88 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -498,6 +498,7 @@
mb(); /* make sure all registers updated */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
mb();
}
}
@@ -525,6 +526,7 @@
mb(); /* make sure all registers updated */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
mb();
mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE);
} else {
@@ -589,6 +591,7 @@
dsi_pipe->blt_cnt = 0;
dsi_pipe->ov_cnt = 0;
dsi_pipe->dmap_cnt = 0;
+ mdp4_stat.blt_dsi_video++;
change++;
} else if (enable == 0 && dsi_pipe->blt_addr) {
dsi_pipe->blt_addr = 0;
@@ -698,5 +701,4 @@
mdp4_overlay_reg_flush(pipe, 1);
mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
mutex_unlock(&mfd->dma->ov_mutex);
- mdp4_stat.kickoff_dsi++;
}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 636d350..d0c86d0 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -464,7 +464,5 @@
mfd->ov_end = true;
}
mdp4_overlay_dtv_ov_done_push(mfd, pipe);
-
- mdp4_stat.kickoff_dtv++;
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index f44a409..a8e39d0 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -422,6 +422,7 @@
mb(); /* make sure all registers updated */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
mb();
mdp4_overlay_lcdc_wait4event(mfd, INTR_DMA_P_DONE);
} else {
@@ -485,6 +486,7 @@
lcdc_pipe->blt_cnt = 0;
lcdc_pipe->ov_cnt = 0;
lcdc_pipe->dmap_cnt = 0;
+ mdp4_stat.blt_lcdc++;
} else if (enable == 0 && lcdc_pipe->blt_addr) {
lcdc_pipe->blt_addr = 0;
change++;
@@ -572,5 +574,4 @@
mdp4_overlay_reg_flush(pipe, 1);
mdp4_overlay_lcdc_vsync_push(mfd, pipe);
mutex_unlock(&mfd->dma->ov_mutex);
- mdp4_stat.kickoff_lcdc++;
}
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 928ac32..83959df 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -475,6 +475,7 @@
mfd->dma->busy = TRUE;
/* start OVERLAY pipe */
mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+ mdp4_stat.kickoff_ov0++;
}
void mdp4_dma_s_update_lcd(struct msm_fb_data_type *mfd,
@@ -557,6 +558,7 @@
mfd->ibuf_flushed = TRUE;
/* start dma_s pipe */
mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+ mdp4_stat.kickoff_dmas++;
/* wait until DMA finishes the current job */
wait_for_completion(&mfd->dma->comp);
@@ -593,8 +595,6 @@
} else /* no dams dmap switch */
mdp4_mddi_kickoff_ui(mfd, mddi_pipe);
- mdp4_stat.kickoff_mddi++;
-
/* signal if pan function is waiting for the update completion */
if (mfd->pan_waiting) {
mfd->pan_waiting = FALSE;
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index f96c7ea..f51427c 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -400,6 +400,7 @@
panel = mdp4_overlay_panel_list();
if (isr & INTR_PRIMARY_VSYNC) {
+ mdp4_stat.intr_vsync_p++;
dma = &dma2_data;
spin_lock(&mdp_spin_lock);
mdp_intr_mask &= ~INTR_PRIMARY_VSYNC;
@@ -415,6 +416,7 @@
}
#ifdef CONFIG_FB_MSM_DTV
if (isr & INTR_EXTERNAL_VSYNC) {
+ mdp4_stat.intr_vsync_e++;
dma = &dma_e_data;
spin_lock(&mdp_spin_lock);
mdp_intr_mask &= ~INTR_EXTERNAL_VSYNC;
@@ -548,6 +550,7 @@
spin_unlock(&mdp_spin_lock);
}
if (isr & INTR_DMA_P_HISTOGRAM) {
+ mdp4_stat.intr_histogram++;
isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
diff --git a/drivers/video/msm/mdp_debugfs.c b/drivers/video/msm/mdp_debugfs.c
index b89e8c7..9ae1d9c 100644
--- a/drivers/video/msm/mdp_debugfs.c
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -272,7 +272,6 @@
int tot = 0;
int dlen;
char *bp;
- unsigned long flag;
if (*ppos)
@@ -281,124 +280,210 @@
bp = debug_buf;
dlen = sizeof(debug_buf);
- spin_lock_irqsave(&mdp_spin_lock, flag);
- len = snprintf(bp, dlen, "intr_total: %08lu\n",
+ len = snprintf(bp, dlen, "\nmdp:\n");
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "int_total: %08lu\t",
mdp4_stat.intr_tot);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "intr_dma_p: %08lu\n",
- mdp4_stat.intr_dma_p);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "intr_dma_s: %08lu\n",
- mdp4_stat.intr_dma_s);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "intr_dma_e: %08lu\n",
- mdp4_stat.intr_dma_e);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "intr_overlay0: %08lu\n",
+
+ len = snprintf(bp, dlen, "int_overlay0: %08lu\t",
mdp4_stat.intr_overlay0);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "intr_overlay1: %08lu\n",
+ len = snprintf(bp, dlen, "int_overlay1: %08lu\n",
mdp4_stat.intr_overlay1);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "unerrun_primary: %08lu\n",
+
+ len = snprintf(bp, dlen, "int_dmap: %08lu\t",
+ mdp4_stat.intr_dma_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_dmas: %08lu\t",
+ mdp4_stat.intr_dma_s);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_dmae: %08lu\n",
+ mdp4_stat.intr_dma_e);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "primary: vsync: %08lu\t",
+ mdp4_stat.intr_vsync_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "underrun: %08lu\n",
mdp4_stat.intr_underrun_p);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "unerrun_external: %08lu\n\n",
+ len = snprintf(bp, dlen, "external: vsync: %08lu\t",
+ mdp4_stat.intr_vsync_e);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "underrun: %08lu\n",
mdp4_stat.intr_underrun_e);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "intr_dsi : %08lu\n\n",
- mdp4_stat.intr_dsi);
+ len = snprintf(bp, dlen, "histogram: %08lu\t",
+ mdp4_stat.intr_histogram);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "read_ptr: %08lu\n\n",
+ mdp4_stat.intr_rd_ptr);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dsi:\n");
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_total: %08lu\tmdp_start: %08lu\n",
+ mdp4_stat.intr_dsi, mdp4_stat.dsi_mdp_start);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_cmd: %08lu\t",
+ mdp4_stat.intr_dsi_cmd);
bp += len;
dlen -= len;
- spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
- len = snprintf(bp, dlen, "kickoff_mddi: %08lu\n",
- mdp4_stat.kickoff_mddi);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "kickoff_lcdc: %08lu\n",
- mdp4_stat.kickoff_lcdc);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "kickoff_dtv: %08lu\n",
- mdp4_stat.kickoff_dtv);
+ len = snprintf(bp, dlen, "int_mdp: %08lu\t",
+ mdp4_stat.intr_dsi_mdp);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "kickoff_atv: %08lu\n",
- mdp4_stat.kickoff_atv);
+
+ len = snprintf(bp, dlen, "int_err: %08lu\n",
+ mdp4_stat.intr_dsi_err);
+
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "kickoff_dsi: %08lu\n\n",
- mdp4_stat.kickoff_dsi);
+ len = snprintf(bp, dlen, "clk_on : %08lu\t",
+ mdp4_stat.dsi_clk_on);
+
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "writeback: %08lu\n",
- mdp4_stat.writeback);
+ len = snprintf(bp, dlen, "clk_off: %08lu\n\n",
+ mdp4_stat.dsi_clk_off);
+
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "overlay0_set: %08lu\n",
+ len = snprintf(bp, dlen, "kickoff:\n");
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "overlay0: %08lu\t",
+ mdp4_stat.kickoff_ov0);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dmap: %08lu\t",
+ mdp4_stat.kickoff_dmap);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dmas: %08lu\n",
+ mdp4_stat.kickoff_dmas);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1: %08lu\t",
+ mdp4_stat.kickoff_ov1);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dmae: %08lu\n\n",
+ mdp4_stat.kickoff_dmae);
+
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "overlay0_play:\n");
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "set: %08lu\t",
mdp4_stat.overlay_set[0]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "overlay0_unset: %08lu\n",
+ len = snprintf(bp, dlen, "unset: %08lu\t",
mdp4_stat.overlay_unset[0]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "overlay0_play: %08lu\n",
+ len = snprintf(bp, dlen, "play: %08lu\n",
mdp4_stat.overlay_play[0]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "overlay1_set: %08lu\n",
+
+ len = snprintf(bp, dlen, "overlay1_play:\n");
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "set: %08lu\t",
mdp4_stat.overlay_set[1]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "overlay1_unset: %08lu\n",
+ len = snprintf(bp, dlen, "unset: %08lu\t",
mdp4_stat.overlay_unset[1]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "overlay1_play: %08lu\n\n",
+ len = snprintf(bp, dlen, "play: %08lu\n\n",
mdp4_stat.overlay_play[1]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "pipe_rgb1: %08lu\n", mdp4_stat.pipe[0]);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "pipe_rgb2: %08lu\n", mdp4_stat.pipe[1]);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "pipe_vg1: %08lu\n", mdp4_stat.pipe[2]);
- bp += len;
- dlen -= len;
- len = snprintf(bp, dlen, "pipe_vg2: %08lu\n\n", mdp4_stat.pipe[3]);
+ len = snprintf(bp, dlen, "frame_push:\n");
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "dsi_clkoff: %08lu\n\n", mdp4_stat.dsi_clkoff);
+ len = snprintf(bp, dlen, "rgb1: %08lu\t\t", mdp4_stat.pipe[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "rgb2: %08lu\n", mdp4_stat.pipe[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "vg1: %08lu\t\t", mdp4_stat.pipe[2]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "vg2: %08lu\n", mdp4_stat.pipe[3]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_mixer: %08lu\t", mdp4_stat.err_mixer);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_size : %08lu\n", mdp4_stat.err_size);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_scale: %08lu\t", mdp4_stat.err_scale);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_format: %08lu\n\n", mdp4_stat.err_format);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "writeback:\n");
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_mixer: %08lu\n", mdp4_stat.err_mixer);
+
+ len = snprintf(bp, dlen, "dsi_cmd: %08lu\t",
+ mdp4_stat.blt_dsi_cmd);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_size: %08lu\n", mdp4_stat.err_size);
+
+ len = snprintf(bp, dlen, "dsi_video: %08lu\n",
+ mdp4_stat.blt_dsi_video);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_scale: %08lu\n", mdp4_stat.err_scale);
+
+ len = snprintf(bp, dlen, "lcdc: %08lu\t",
+ mdp4_stat.blt_lcdc);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_format: %08lu\n", mdp4_stat.err_format);
+
+ len = snprintf(bp, dlen, "dtv: %08lu\t",
+ mdp4_stat.blt_dtv);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "mddi: %08lu\n\n",
+ mdp4_stat.blt_mddi);
bp += len;
dlen -= len;
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 8d07e56..f2e2f10 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -51,6 +51,39 @@
static struct list_head pre_kickoff_list;
static struct list_head post_kickoff_list;
+enum {
+ STAT_DSI_START,
+ STAT_DSI_ERROR,
+ STAT_DSI_CMD,
+ STAT_DSI_MDP
+};
+
+#ifdef CONFIG_FB_MSM_MDP40
+void mipi_dsi_mdp_stat_inc(int which)
+{
+ switch (which) {
+ case STAT_DSI_START:
+ mdp4_stat.dsi_mdp_start++;
+ break;
+ case STAT_DSI_ERROR:
+ mdp4_stat.intr_dsi_err++;
+ break;
+ case STAT_DSI_CMD:
+ mdp4_stat.intr_dsi_cmd++;
+ break;
+ case STAT_DSI_MDP:
+ mdp4_stat.intr_dsi_mdp++;
+ break;
+ default:
+ break;
+ }
+}
+#else
+void mipi_dsi_mdp_stat_inc(int which)
+{
+}
+#endif
+
void mipi_dsi_init(void)
{
init_completion(&dsi_dma_comp);
@@ -986,6 +1019,7 @@
__func__, current->pid);
}
+
void mipi_dsi_cmd_mdp_start(void)
{
unsigned long flag;
@@ -994,6 +1028,8 @@
if (!in_interrupt())
mipi_dsi_pre_kickoff_action();
+ mipi_dsi_mdp_stat_inc(STAT_DSI_START);
+
spin_lock_irqsave(&dsi_mdp_lock, flag);
mipi_dsi_enable_irq();
dsi_mdp_busy = TRUE;
@@ -1438,6 +1474,7 @@
#endif
if (isr & DSI_INTR_ERROR) {
+ mipi_dsi_mdp_stat_inc(STAT_DSI_ERROR);
mipi_dsi_error();
}
@@ -1448,10 +1485,12 @@
}
if (isr & DSI_INTR_CMD_DMA_DONE) {
+ mipi_dsi_mdp_stat_inc(STAT_DSI_CMD);
complete(&dsi_dma_comp);
}
if (isr & DSI_INTR_CMD_MDP_DONE) {
+ mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
spin_lock(&dsi_mdp_lock);
dsi_mdp_busy = FALSE;
spin_unlock(&dsi_mdp_lock);
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index ba93df76..52a10ab 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -12,6 +12,8 @@
*/
#include <linux/clk.h>
#include "msm_fb.h"
+#include "mdp.h"
+#include "mdp4.h"
#include "mipi_dsi.h"
#include "hdmi_msm.h"
#include <mach/msm_iomap.h>
@@ -555,6 +557,7 @@
mipi_dsi_clk_ctrl(&dsicore_clk, 1);
clk_enable(dsi_byte_div_clk);
clk_enable(dsi_esc_clk);
+ mdp4_stat.dsi_clk_on++;
}
void mipi_dsi_clk_disable(void)
@@ -565,6 +568,7 @@
mipi_dsi_clk_ctrl(&dsicore_clk, 0);
/* DSIPHY_PLL_CTRL_0, disable dsi pll */
MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x0);
+ mdp4_stat.dsi_clk_off++;
}
void mipi_dsi_phy_ctrl(int on)
diff --git a/include/linux/earlysuspend.h b/include/linux/earlysuspend.h
old mode 100755
new mode 100644
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
old mode 100755
new mode 100644
diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h
old mode 100755
new mode 100644
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
new file mode 100644
index 0000000..2fd1604
--- /dev/null
+++ b/include/sound/compress_driver.h
@@ -0,0 +1,150 @@
+/*
+ * compress_driver.h - compress offload driver definations
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Authors: Vinod Koul <vinod.koul@linux.intel.com>
+ * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_DRIVER_H
+#define __COMPRESS_DRIVER_H
+
+#include <sound/compress_offload.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+
+struct snd_compr_ops;
+
+/**
+ * struct snd_compr_runtime: runtime stream description
+ * @state: stream state
+ * @ops: pointer to DSP callbacks
+ * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
+ * DSP doesn't implement copy
+ * @buffer_size: size of the above buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ * @hw_pointer: offset of last location in buffer where DSP copied data
+ * @app_pointer: offset of last location in buffer where app wrote data
+ * @sleep: poll sleep
+ */
+struct snd_compr_runtime {
+ snd_pcm_state_t state;
+ struct snd_compr_ops *ops;
+ void *buffer;
+ size_t buffer_size;
+ size_t fragment_size;
+ unsigned int fragments;
+ size_t hw_pointer;
+ size_t app_pointer;
+ wait_queue_head_t sleep;
+};
+
+/**
+ * struct snd_compr_stream: compressed stream
+ * @name: device name
+ * @ops: pointer to DSP callbacks
+ * @runtime: pointer to runtime structure
+ * @device: device pointer
+ * @direction: stream direction, playback/recording
+ * @private_data: pointer to DSP private data
+ */
+struct snd_compr_stream {
+ const char *name;
+ struct snd_compr_ops *ops;
+ struct snd_compr_runtime *runtime;
+ struct snd_compr *device;
+ unsigned int direction;
+ void *private_data;
+};
+
+/**
+ * struct snd_compr_ops: compressed path DSP operations
+ * @open: Open the compressed stream
+ * This callback is mandatory and shall keep dsp ready to receive the stream
+ * parameter
+ * @free: Close the compressed stream, mandatory
+ * @set_params: Sets the compressed stream parameters, mandatory
+ * This can be called in during stream creation only to set codec params
+ * and the stream properties
+ * @get_params: retrieve the codec parameters, mandatory
+ * @trigger: Trigger operations like start, pause, resume, drain, stop.
+ * This callback is mandatory
+ * @pointer: Retrieve current h/w pointer information. Mandatory
+ * @copy: Copy the compressed data to/from userspace, Optional
+ * Can't be implemented if DSP supports mmap
+ * @mmap: DSP mmap method to mmap DSP memory
+ * @ack: Ack for DSP when data is written to audio buffer, Optional
+ * Not valid if copy is implemented
+ * @get_caps: Retrieve DSP capabilities, mandatory
+ * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
+ */
+struct snd_compr_ops {
+ int (*open)(struct snd_compr_stream *stream);
+ int (*free)(struct snd_compr_stream *stream);
+ int (*set_params)(struct snd_compr_stream *stream,
+ struct snd_compr_params *params);
+ int (*get_params)(struct snd_compr_stream *stream,
+ struct snd_compr_params *params);
+ int (*trigger)(struct snd_compr_stream *stream, int cmd);
+ int (*pointer)(struct snd_compr_stream *stream,
+ struct snd_compr_tstamp *tstamp);
+ int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
+ size_t count);
+ int (*mmap)(struct snd_compr_stream *stream,
+ struct vm_area_struct *vma);
+ int (*ack)(struct snd_compr_stream *stream);
+ int (*get_caps) (struct snd_compr_stream *stream,
+ struct snd_compr_caps *caps);
+ int (*get_codec_caps) (struct snd_compr_stream *stream,
+ struct snd_compr_codec_caps *codec);
+};
+
+/**
+ * struct snd_compr: Compressed device
+ * @name: DSP device name
+ * @dev: Device pointer
+ * @lock: device lock
+ * @ops: pointer to DSP callbacks
+ * @private_data: pointer to DSP pvt data
+ */
+struct snd_compr {
+ const char *name;
+ struct device *dev;
+ struct mutex lock;
+ struct snd_compr_ops *ops;
+ struct list_head list;
+ void *private_data;
+};
+
+/* compress device register APIs */
+int snd_compress_register(struct snd_compr *device);
+int snd_compress_deregister(struct snd_compr *device);
+
+/* dsp driver callback apis
+ * For playback: driver should call snd_compress_fragment_elapsed() to let the
+ * framework know that a fragment has been consumed from the ring buffer
+ * For recording: we may want to know when a frame is available or when
+ * at least one frame is available for userspace, a different
+ * snd_compress_frame_elapsed() callback should be used
+ */
+void snd_compr_fragment_elapsed(struct snd_compr_stream *stream);
+void snd_compr_frame_elapsed(struct snd_compr_stream *stream);
+
+#endif
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
new file mode 100644
index 0000000..423264d
--- /dev/null
+++ b/include/sound/compress_offload.h
@@ -0,0 +1,137 @@
+/*
+ * compress_offload.h - compress offload header definations
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Authors: Vinod Koul <vinod.koul@linux.intel.com>
+ * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+/**
+ * struct snd_compressed_buffer:compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+ size_t fragment_size;
+ int fragments;
+};
+
+/* */
+struct snd_compr_params {
+ struct snd_compressed_buffer buffer;
+ struct snd_codec codec;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @copied_bytes: Number of bytes offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from ring buffer to DSP
+ * @decoded: Frames decoded by DSP
+ * @rendered: Frames rendered by DSP into a mixer or an audio output
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+ size_t copied_bytes;
+ size_t copied_total;
+ size_t decoded;
+ size_t rendered;
+ __u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+ size_t avail;
+ struct snd_compr_tstamp tstamp;
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+ __u32 num_codecs;
+ __u32 min_fragment_size;
+ __u32 max_fragment_size;
+ __u32 min_fragments;
+ __u32 max_fragments;
+ __u32 codecs[MAX_NUM_CODECS];
+ __u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+ __u32 codec;
+ __u32 num_descriptors;
+ struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec and stream params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ */
+#define SNDRV_COMPRESS_GET_CAPS _IOWR('C', 0x00, struct snd_compr_caps *)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS _IOWR('C', 0x01, struct snd_compr_codec_caps *)
+#define SNDRV_COMPRESS_SET_PARAMS _IOW('C', 0x02, struct snd_compr_params *)
+#define SNDRV_COMPRESS_GET_PARAMS _IOR('C', 0x03, struct snd_compr_params *)
+#define SNDRV_COMPRESS_TSTAMP _IOR('C', 0x10, struct snd_compr_tstamp *)
+#define SNDRV_COMPRESS_AVAIL _IOR('C', 0x11, struct snd_compr_avail *)
+#define SNDRV_COMPRESS_PAUSE _IO('C', 0x20)
+#define SNDRV_COMPRESS_RESUME _IO('C', 0x21)
+#define SNDRV_COMPRESS_START _IO('C', 0x22)
+#define SNDRV_COMPRESS_STOP _IO('C', 0x23)
+#define SNDRV_COMPRESS_DRAIN _IO('C', 0x24)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
new file mode 100644
index 0000000..5080e13
--- /dev/null
+++ b/include/sound/snd_compress_params.h
@@ -0,0 +1,392 @@
+/*
+ * snd_compress_params.h - codec types and parameters for compressed data
+ * streaming interface
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Authors: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ * Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3 ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937 ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D)
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2 ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1 ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2 ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2 ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7 ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8 ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9 ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10 ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1 ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3 ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4 ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1 ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2 ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3 ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2 ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10 ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0 ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2 ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3 ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5 ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6 ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8 ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937 ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1 ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3 ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3 ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2 ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1 ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729 ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+ an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+ __u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set bitrate management mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+ int quality;
+ __u32 managed;
+ __u32 max_bit_rate;
+ __u32 min_bit_rate;
+ __u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+ __u32 quant_bits;
+ __u32 start_region;
+ __u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ * needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+ __u32 num;
+ __u32 gain;
+};
+
+struct snd_enc_generic {
+ __u32 bw; /* encoder bandwidth */
+ int reserved[15];
+};
+
+union snd_codec_options {
+ struct snd_enc_wma wma;
+ struct snd_enc_vorbis vorbis;
+ struct snd_enc_real real;
+ struct snd_enc_flac flac;
+ struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+ __u32 max_ch;
+ __u32 sample_rates;
+ __u32 bit_rate[MAX_NUM_BITRATES];
+ __u32 num_bitrates;
+ __u32 rate_control;
+ __u32 profiles;
+ __u32 modes;
+ __u32 formats;
+ __u32 reserved[16];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ * See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ * this field and the channelMode field, the channelMode field
+ * overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ * Encoders may rely on profiles for quality levels.
+ * May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ * decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ * See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ * Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+ __u32 id;
+ __u32 ch_in;
+ __u32 ch_out;
+ __u32 sample_rate;
+ __u32 bit_rate;
+ __u32 rate_control;
+ __u32 profile;
+ __u32 level;
+ __u32 ch_mode;
+ __u32 format;
+ __u32 align;
+ union snd_codec_options options;
+ __u32 reserved[3];
+};
diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
new file mode 100644
index 0000000..987594a
--- /dev/null
+++ b/sound/compress_offload/core.c
@@ -0,0 +1,658 @@
+/*
+ * core.c - compress offload core
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Authors: Vinod Koul <vinod.koul@linux.intel.com>
+ * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+/* TODO:
+ * - Integrate with alsa, compressed devices should register as alsa devices
+ * as /dev/snd_compr_xxx
+ * - Integrate with ASoC:
+ * Opening compressed path should also start the codec dai
+ * TBD how the cpu dai will be viewed and started.
+ * ASoC should always be optional part
+ * (we should be able to use this framework in non asoc systems
+ * - Multiple node representation
+ * driver should be able to register multiple nodes
+ * - Version numbering for API
+ */
+
+static DEFINE_MUTEX(device_mutex);
+static LIST_HEAD(device_list);
+static LIST_HEAD(misc_list);
+
+/*
+ * currently we are using misc device for registration and exposing ioctls
+ * this is temporary and will be moved to snd
+ * the device should be registered as /dev/snd_compr.....
+ */
+
+struct snd_compr_misc {
+ struct miscdevice misc;
+ struct list_head list;
+ struct snd_compr *compr;
+};
+
+struct snd_ioctl_data {
+ struct snd_compr_misc *misc;
+ unsigned long caps;
+ unsigned int minor;
+ struct snd_compr_stream stream;
+};
+
+static struct snd_compr_misc *snd_compr_get_device(unsigned int minor)
+{
+ struct snd_compr_misc *misc;
+
+ list_for_each_entry(misc, &misc_list, list) {
+ if (minor == misc->misc.minor)
+ return misc;
+ }
+ return NULL;
+}
+
+static int snd_compr_open(struct inode *inode, struct file *f)
+{
+ unsigned int minor = iminor(inode);
+ struct snd_compr_misc *misc = snd_compr_get_device(minor);
+ struct snd_ioctl_data *data;
+ struct snd_compr_runtime *runtime;
+ unsigned int direction;
+ int ret;
+
+ mutex_lock(&device_mutex);
+ if (f->f_flags & O_WRONLY)
+ direction = SNDRV_PCM_STREAM_PLAYBACK;
+ else {
+ ret = -ENXIO;
+ goto out;
+ }
+ /* curently only encoded playback is supported, above needs to be
+ * removed once we have recording support */
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ data->misc = misc;
+ data->minor = minor;
+ data->stream.ops = misc->compr->ops;
+ data->stream.direction = direction;
+ data->stream.private_data = misc->compr->private_data;
+ data->stream.device = misc->compr;
+ runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+ if (!runtime) {
+ ret = -ENOMEM;
+ kfree(data);
+ goto out;
+ }
+ runtime->state = SNDRV_PCM_STATE_OPEN;
+ init_waitqueue_head(&runtime->sleep);
+ data->stream.runtime = runtime;
+ f->private_data = (void *)data;
+ ret = misc->compr->ops->open(&data->stream);
+ if (ret) {
+ kfree(runtime);
+ kfree(data);
+ goto out;
+ }
+out:
+ mutex_unlock(&device_mutex);
+ return ret;
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+ struct snd_ioctl_data *data = f->private_data;
+ mutex_lock(&device_mutex);
+ data->stream.ops->free(&data->stream);
+ kfree(data->stream.runtime->buffer);
+ kfree(data->stream.runtime);
+ kfree(data);
+ mutex_unlock(&device_mutex);
+ return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+ struct snd_compr_tstamp *tstamp)
+{
+ stream->ops->pointer(stream, tstamp);
+ stream->runtime->hw_pointer = tstamp->copied_bytes;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+ struct snd_compr_avail *avail)
+{
+ size_t avail_calc;
+
+ snd_compr_update_tstamp(stream, &avail->tstamp);
+ avail_calc = stream->runtime->app_pointer - stream->runtime->hw_pointer;
+ if (avail_calc < 0)
+ avail_calc = stream->runtime->buffer_size + avail_calc;
+ avail->avail = avail_calc;
+ return avail_calc;
+}
+
+static size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+ struct snd_compr_avail avail;
+
+ return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_avail ioctl_avail;
+
+ snd_compr_calc_avail(stream, &ioctl_avail);
+
+ if (copy_to_user((unsigned long __user *)arg, &ioctl_avail, sizeof(ioctl_avail)))
+ return -EFAULT;
+ return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+ const char __user *buf, size_t count)
+{
+ void *dstn;
+ size_t copy;
+
+ dstn = stream->runtime->buffer + stream->runtime->app_pointer;
+ if (count < stream->runtime->buffer_size - stream->runtime->app_pointer) {
+ if (copy_from_user(dstn, buf, count))
+ return -EFAULT;
+ stream->runtime->app_pointer += count;
+ } else {
+ copy = stream->runtime->buffer_size - stream->runtime->app_pointer;
+ if (copy_from_user(dstn, buf, copy))
+ return -EFAULT;
+ if (copy_from_user(stream->runtime->buffer, buf + copy, count - copy))
+ return -EFAULT;
+ stream->runtime->app_pointer = count - copy;
+ }
+ /* if DSP cares, let it know data has been written */
+ if (stream->ops->ack)
+ stream->ops->ack(stream);
+ return count;
+}
+
+static ssize_t snd_compr_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct snd_ioctl_data *data = f->private_data;
+ struct snd_compr_stream *stream;
+ size_t avail;
+ int retval;
+
+ BUG_ON(!data);
+ stream = &data->stream;
+ mutex_lock(&stream->device->lock);
+ /* write is allowed when stream is running or has been steup */
+ if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+ stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+ mutex_unlock(&stream->device->lock);
+ return -EPERM;
+ }
+
+ avail = snd_compr_get_avail(stream);
+ /* calculate how much we can write to buffer */
+ if (avail > count)
+ avail = count;
+
+ if (stream->ops->copy)
+ retval = stream->ops->copy(stream, buf, avail);
+ else
+ retval = snd_compr_write_data(stream, buf, avail);
+
+ /* while initiating the stream, write should be called before START
+ * call, so in setup move state */
+ if (stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+ stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+
+ mutex_unlock(&stream->device->lock);
+ return retval;
+}
+
+
+static ssize_t snd_compr_read(struct file *f, char __user *buf,
+ size_t count, loff_t *offset)
+{
+ return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+ return -ENXIO;
+}
+
+unsigned int snd_compr_poll(struct file *f, poll_table *wait)
+{
+ struct snd_ioctl_data *data = f->private_data;
+ struct snd_compr_stream *stream;
+ int retval = 0;
+
+ BUG_ON(!data);
+ stream = &data->stream;
+
+ mutex_lock(&stream->device->lock);
+ if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+ retval = -ENXIO;
+ goto out;
+ }
+ poll_wait(f, &stream->runtime->sleep, wait);
+
+ /* this would change after read is implemented, we would need to
+ * check for direction here */
+ if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+ retval = POLLOUT | POLLWRNORM;
+out:
+ mutex_unlock(&stream->device->lock);
+ return retval;
+}
+
+void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
+{
+ size_t avail;
+
+ if (stream->direction != SNDRV_PCM_STREAM_PLAYBACK)
+ return;
+ avail = snd_compr_get_avail(stream);
+ if (avail >= stream->runtime->fragment_size)
+ wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
+
+void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
+{
+ size_t avail;
+
+ if (stream->direction != SNDRV_PCM_STREAM_CAPTURE)
+ return;
+ avail = snd_compr_get_avail(stream);
+ if (avail)
+ wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
+
+static int snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+ int retval;
+ struct snd_compr_caps caps;
+
+ if (!stream->ops->get_caps)
+ return -ENXIO;
+
+ retval = stream->ops->get_caps(stream, &caps);
+ if (retval)
+ goto out;
+ if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+ retval = -EFAULT;
+out:
+ return retval;
+}
+
+static int snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+ int retval;
+ struct snd_compr_codec_caps *caps;
+
+ if (!stream->ops->get_codec_caps)
+ return -ENXIO;
+
+ caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+ if (!caps)
+ return -ENOMEM;
+
+ retval = stream->ops->get_codec_caps(stream, caps);
+ if (retval)
+ goto out;
+ if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+ retval = -EFAULT;
+
+out:
+ kfree(caps);
+ return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+ struct snd_compr_params *params)
+{
+ unsigned int buffer_size;
+ void *buffer;
+
+ buffer_size = params->buffer.fragment_size * params->buffer.fragments;
+ if (stream->ops->copy) {
+ buffer = NULL;
+ /* if copy is defined the driver will be required to copy
+ * the data from core
+ */
+ } else {
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ }
+ stream->runtime->fragment_size = params->buffer.fragment_size;
+ stream->runtime->fragments = params->buffer.fragments;
+ stream->runtime->buffer = buffer;
+ stream->runtime->buffer_size = buffer_size;
+ return 0;
+}
+
+static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_params *params;
+ int retval;
+
+ if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+ /*
+ * we should allow parameter change only when stream has been
+ * opened not in other cases
+ */
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
+ return -EFAULT;
+ retval = snd_compr_allocate_buffer(stream, params);
+ if (retval) {
+ kfree(params);
+ return -ENOMEM;
+ }
+ retval = stream->ops->set_params(stream, params);
+ if (retval)
+ goto out;
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+ } else
+ return -EPERM;
+out:
+ kfree(params);
+ return retval;
+}
+
+static int snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_params *params;
+ int retval;
+
+ if (!stream->ops->get_params)
+ return -ENXIO;
+
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ retval = stream->ops->get_params(stream, params);
+ if (retval)
+ goto out;
+ if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+ retval = -EFAULT;
+
+out:
+ kfree(params);
+ return retval;
+}
+
+static int snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_tstamp tstamp;
+
+ snd_compr_update_tstamp(stream, &tstamp);
+ if (copy_to_user((struct snd_compr_tstamp __user *)arg, &tstamp, sizeof(tstamp)))
+ return -EFAULT;
+ return 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED)
+ return 0;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+ if (!retval) {
+ stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+ wake_up(&stream->runtime->sleep);
+ }
+ return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+ if (!retval)
+ stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+ return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+ if (!retval)
+ stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+ return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+ if (!retval) {
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+ wake_up(&stream->runtime->sleep);
+ }
+ return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
+ stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+ if (!retval) {
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+ wake_up(&stream->runtime->sleep);
+ }
+ return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+ struct snd_ioctl_data *data = f->private_data;
+ struct snd_compr_stream *stream;
+ int retval = -ENOTTY;
+
+ BUG_ON(!data);
+ stream = &data->stream;
+ mutex_lock(&stream->device->lock);
+ switch (_IOC_NR(cmd)) {
+ case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+ retval = snd_compr_get_caps(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+ retval = snd_compr_get_codec_caps(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+ retval = snd_compr_set_params(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+ retval = snd_compr_get_params(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+ retval = snd_compr_tstamp(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+ retval = snd_compr_ioctl_avail(stream, arg);
+ case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+ retval = snd_compr_pause(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_RESUME):
+ retval = snd_compr_resume(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_START):
+ retval = snd_compr_start(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_STOP):
+ retval = snd_compr_stop(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+ cmd = SND_COMPR_TRIGGER_DRAIN;
+ retval = snd_compr_drain(stream);
+ break;
+ }
+ mutex_unlock(&stream->device->lock);
+ return retval;
+}
+
+static const struct file_operations snd_comp_file = {
+ .owner = THIS_MODULE,
+ .open = snd_compr_open,
+ .release = snd_compr_free,
+ .read = snd_compr_read,
+ .write = snd_compr_write,
+ .unlocked_ioctl = snd_compr_ioctl,
+ .mmap = snd_compr_mmap,
+ .poll = snd_compr_poll,
+};
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+ int ret;
+
+ struct snd_compr_misc *misc = kzalloc(sizeof(*misc), GFP_KERNEL);
+
+ misc->misc.name = device->name;
+ misc->misc.fops = &snd_comp_file;
+ misc->misc.minor = MISC_DYNAMIC_MINOR;
+ misc->compr = device;
+ ret = misc_register(&misc->misc);
+ if (ret) {
+ pr_err("couldn't register misc device\n");
+ kfree(misc);
+ } else {
+ pr_debug("Got minor %d\n", misc->misc.minor);
+ list_add_tail(&misc->list, &misc_list);
+ }
+ return ret;
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+ struct snd_compr_misc *misc, *__misc;
+
+ list_for_each_entry_safe(misc, __misc, &misc_list, list) {
+ if (device == misc->compr) {
+ misc_deregister(&misc->misc);
+ list_del(&device->list);
+ kfree(misc);
+ }
+ }
+ return 0;
+}
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+ int retval;
+
+ if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+ return -EINVAL;
+ BUG_ON(!device->ops->open);
+ BUG_ON(!device->ops->free);
+ BUG_ON(!device->ops->set_params);
+ BUG_ON(!device->ops->get_params);
+ BUG_ON(!device->ops->trigger);
+ BUG_ON(!device->ops->pointer);
+ BUG_ON(!device->ops->get_caps);
+ BUG_ON(!device->ops->get_codec_caps);
+
+ INIT_LIST_HEAD(&device->list);
+ /* todo register the compressed streams */
+ /* todo integrate with asoc */
+
+ /* register a compressed card TBD if this needs change */
+
+ pr_debug("Registering compressed device %s\n", device->name);
+ mutex_lock(&device_mutex);
+ /* register a msic device for now */
+ retval = snd_compress_add_device(device);
+ if (!retval)
+ list_add_tail(&device->list, &device_list);
+ mutex_unlock(&device_mutex);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+ pr_debug("Removing compressed device %s\n", device->name);
+ mutex_lock(&device_mutex);
+ snd_compress_remove_device(device);
+ list_del(&device->list);
+ mutex_unlock(&device_mutex);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+ return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);