From patchwork Tue Nov 30 17:12:56 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Panizzo X-Patchwork-Id: 367471 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 oAUHDV2O008205 for ; Tue, 30 Nov 2010 17:13:31 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754069Ab0K3RNI (ORCPT ); Tue, 30 Nov 2010 12:13:08 -0500 Received: from mail-ww0-f44.google.com ([74.125.82.44]:37637 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751806Ab0K3RNF (ORCPT ); Tue, 30 Nov 2010 12:13:05 -0500 Received: by wwa36 with SMTP id 36so6295503wwa.1 for ; Tue, 30 Nov 2010 09:13:04 -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=4zoF0ZrSxbyknc8s6A4eYwXBe23afo4SxF25BrUMXbc=; b=Xl6viXnAAWoILGKB3lgrUvdF2eoxaZUYoXN+xBAf1uuWgC30DKe9p3ROPhEKJ8Dxj2 Lv+31zraaqNunbytfw+gbF7hAeHpf1vnKazbUmSVbxCrZgtB0NHZ0MvaMKw9KSASLLB7 KwjakqVlli0+rtj/f1BTx1viAFNJ3CRmA+2Tc= 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=sOToXy78cZhDFAawu631GLc5O4M3VUY9XKtP675uKuJuTH1uQnCs0+BprOr0JSMsW2 YDihQSAabMETzSZ00lFVYQRJEOH2mH2kyLhlq9ueFyXK+yOuYtPvgZ1XqGP7EfmWgEyR Z0zss7BTWueiSEmczZUITwo4rc9AGVzOpf+Ng= Received: by 10.227.28.100 with SMTP id l36mr54885wbc.102.1291137184399; Tue, 30 Nov 2010 09:13:04 -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 e12sm3114107wer.12.2010.11.30.09.12.59 (version=SSLv3 cipher=RC4-MD5); Tue, 30 Nov 2010 09:13:03 -0800 (PST) Subject: [PATCH v2] 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: Tue, 30 Nov 2010 18:12:56 +0100 Message-ID: <1291137176.6537.20.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]); Tue, 30 Nov 2010 17:13:31 +0000 (UTC) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 43848a7..f1c2094 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -43,6 +43,41 @@ 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 = 0; + + if (power_on) { + ret = regulator_bulk_enable(icl->num_regulators, + icl->regulators); + } else { + ret = regulator_bulk_disable(icl->num_regulators, + icl->regulators); + } + if (ret < 0) { + dev_err(icd->pdev, "Cannot %s regulators", + power_on ? "ENABLE" : "DISABLE"); + goto err; + } + + if (icl->power) { + ret = icl->power(icd->pdev, power_on); + if (ret < 0) { + dev_err(icd->pdev, + "Platform failed to power %s the camera.\n", + power_on ? "ON" : "OFF"); + goto err; + } + } + + return 0; + +err: + return ret; +} + const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) { @@ -375,11 +410,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 +458,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 +482,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 +972,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) + 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) @@ -1021,8 +1052,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,8 +1074,7 @@ eadddev: evdc: ici->ops->remove(icd); eadd: - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); epower: return ret; } @@ -1081,6 +1110,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..3e6b903 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -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