From patchwork Thu Dec 2 10:43:37 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Panizzo X-Patchwork-Id: 373691 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oB2AiEau028553 for ; Thu, 2 Dec 2010 10:44:15 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757402Ab0LBKno (ORCPT ); Thu, 2 Dec 2010 05:43:44 -0500 Received: from mail-wy0-f174.google.com ([74.125.82.174]:34257 "EHLO mail-wy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757383Ab0LBKnn (ORCPT ); Thu, 2 Dec 2010 05:43:43 -0500 Received: by wyb28 with SMTP id 28so8038054wyb.19 for ; Thu, 02 Dec 2010 02:43:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:subject:from:to:cc :content-type:date:message-id:mime-version:x-mailer :content-transfer-encoding; bh=aUJgMYD5v4F1mg93ZP5nU2HsKHeiWAJeh9nhey06GuE=; b=SGhhtokItd56XBsUk/f6Ovnv4Xfr47f7FPQXha9SR/ZVN27yhABa22KY4uv/GaVIKY BzO7msEuHHhVrOmcRVDWfZYJ4/Vyqi9P914JsSHw2TetNC94My81JJmFg8ZoCpOv3J7A axaUwnnYZljazZxjoKFKr/8waiC06/TV7jzAM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=subject:from:to:cc:content-type:date:message-id:mime-version :x-mailer:content-transfer-encoding; b=Mm4YCCFHUv3/jPnqVQQx32g1uJ1i7jEJqyExwyNm0I6u/puhtLBoe3YqHQSl+56i20 mELYch/XQKZw00w/H7Kgbn+NGuamnPI99u8nZmEar9HEZU7iir1iSb0Zg/T4BHSbSnbm p+zy2OG+R4WD3C0S7wx6rLatuznhl8MBNXxKM= Received: by 10.216.168.148 with SMTP id k20mr2301581wel.11.1291286621769; Thu, 02 Dec 2010 02:43:41 -0800 (PST) Received: from [192.168.1.101] (host-9473-86-114.popwifi.it [94.73.86.114]) by mx.google.com with ESMTPS id 7sm176630wet.0.2010.12.02.02.43.39 (version=SSLv3 cipher=RC4-MD5); Thu, 02 Dec 2010 02:43:40 -0800 (PST) Subject: [PATCH v3] soc_camera: Add the ability to bind regulators to soc_camedra devices From: Alberto Panizzo To: Mauro Carvalho Chehab Cc: Guennadi Liakhovetski , linux-media@vger.kernel.org, linux-kernel , Mark Brown Date: Thu, 02 Dec 2010 11:43:37 +0100 Message-ID: <1291286617.3215.54.camel@realization> Mime-Version: 1.0 X-Mailer: Evolution 2.28.1 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 02 Dec 2010 10:44:16 +0000 (UTC) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 43848a7..136e54f 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,51 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ +static int soc_camera_power_set(struct soc_camera_device *icd, + struct soc_camera_link *icl, + int power_on) +{ + int ret; + + if (power_on) { + ret = regulator_bulk_enable(icl->num_regulators, + icl->regulators); + if (ret < 0) { + dev_err(icd->pdev, "Cannot enable regulators\n"); + return ret; + } + + if (icl->power) + ret = icl->power(icd->pdev, power_on); + if (ret < 0) { + dev_err(icd->pdev, + "Platform failed to power-on the camera.\n"); + + regulator_bulk_disable(icl->num_regulators, + icl->regulators); + return ret; + } + } else { + ret = 0; + if (icl->power) + ret = icl->power(icd->pdev, 0); + if (ret < 0) { + dev_err(icd->pdev, + "Platform failed to power-off the camera.\n"); + return ret; + } + + ret = regulator_bulk_disable(icl->num_regulators, + icl->regulators); + if (ret < 0) { + dev_err(icd->pdev, "Cannot disable regulators\n"); + return ret; + } + } + + return 0; +} + const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) { @@ -375,11 +421,9 @@ static int soc_camera_open(struct file *file) }, }; - if (icl->power) { - ret = icl->power(icd->pdev, 1); - if (ret < 0) - goto epower; - } + ret = soc_camera_power_set(icd, icl, 1); + if (ret < 0) + goto epower; /* The camera could have been already on, try to reset */ if (icl->reset) @@ -425,8 +469,7 @@ esfmt: eresume: ici->ops->remove(icd); eiciadd: - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); epower: icd->use_count--; mutex_unlock(&icd->video_lock); @@ -450,8 +493,7 @@ static int soc_camera_close(struct file *file) ici->ops->remove(icd); - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); } if (icd->streamer == file) @@ -941,14 +983,14 @@ static int soc_camera_probe(struct device *dev) dev_info(dev, "Probing %s\n", dev_name(dev)); - if (icl->power) { - ret = icl->power(icd->pdev, 1); - if (ret < 0) { - dev_err(dev, - "Platform failed to power-on the camera.\n"); - goto epower; - } - } + ret = regulator_bulk_get(icd->pdev, icl->num_regulators, + icl->regulators); + if (ret < 0) + goto ereg; + + ret = soc_camera_power_set(icd, icl, 1); + if (ret < 0) + goto epower; /* The camera could have been already on, try to reset */ if (icl->reset) @@ -1021,8 +1063,7 @@ static int soc_camera_probe(struct device *dev) ici->ops->remove(icd); - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); mutex_unlock(&icd->video_lock); @@ -1044,9 +1085,10 @@ eadddev: evdc: ici->ops->remove(icd); eadd: - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); epower: + regulator_bulk_free(icl->num_regulators, icl->regulators); +ereg: return ret; } @@ -1081,6 +1123,8 @@ static int soc_camera_remove(struct device *dev) } soc_camera_free_user_formats(icd); + regulator_bulk_free(icl->num_regulators, icl->regulators); + return 0; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 86e3631..9386db8 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -97,6 +97,7 @@ struct soc_camera_host_ops { #define SOCAM_SENSOR_INVERT_DATA (1 << 4) struct i2c_board_info; +struct regulator_bulk_data; struct soc_camera_link { /* Camera bus id, used to match a camera and a bus */ @@ -108,6 +109,10 @@ struct soc_camera_link { const char *module_name; void *priv; + /* Optional regulators that have to be managed on power on/off events */ + struct regulator_bulk_data *regulators; + int num_regulators; + /* * For non-I2C devices platform platform has to provide methods to * add a device to the system and to remove