From patchwork Tue Jan 27 07:55:27 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kassey Lee X-Patchwork-Id: 5715191 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 81AC4C058D for ; Tue, 27 Jan 2015 07:55:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 997B6201FE for ; Tue, 27 Jan 2015 07:55:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B46FE201EC for ; Tue, 27 Jan 2015 07:55:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757516AbbA0Hza (ORCPT ); Tue, 27 Jan 2015 02:55:30 -0500 Received: from mail-pa0-f42.google.com ([209.85.220.42]:57859 "EHLO mail-pa0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752179AbbA0Hz2 (ORCPT ); Tue, 27 Jan 2015 02:55:28 -0500 Received: by mail-pa0-f42.google.com with SMTP id bj1so16992454pad.1 for ; Mon, 26 Jan 2015 23:55:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=mlf7xfVWR131j/7WTZiXoQ5bhOIu0QTVeJytq+GAh/Q=; b=ZWoCBACQdo2e4ysTd+B7kfL63ak3AGmh7QV4jM+MTDJe+QCVO0tLbQr8q+KozaMkp9 BDGhaEqEmgaKyr49gndocTGxDNqFcfGRvgc5dLwkyBW5ipoB5KI9HI4ZmKlRWrUBBO+m zUEm27cta0nVxj2WKo1nFisVHzXu03u272zvIH4ZmLYrpScyQ/jx/LEM8V0w8mtbEFCQ RKkpw6hPi6V17b7Wuz4kD3X2XH/IVJxOCf2e11JxZ7Yu+t9W5YC0fTLFRDnNEDBW/i71 knSuuQSI0bIlEzMKi5kjSlpZjZF6aMUJ3CVP5l23xDYsu/S/5CGYiRmVVFh53uK4txwf +y7w== X-Received: by 10.66.149.98 with SMTP id tz2mr4493787pab.63.1422345327576; Mon, 26 Jan 2015 23:55:27 -0800 (PST) Received: from kassey-System-Product-Name.nvidia.com ([203.18.50.4]) by mx.google.com with ESMTPSA id a13sm693716pdm.44.2015.01.26.23.55.24 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 26 Jan 2015 23:55:26 -0800 (PST) From: Kassey Li To: g.liakhovetski@gmx.de Cc: linux-media@vger.kernel.org, kasseyl@nvidia.com Subject: [PATCH V1] [media] V4L: soc-camera: add SPI device support Date: Tue, 27 Jan 2015 15:55:27 +0800 Message-Id: <1422345327-27843-1-git-send-email-kassey1216@gmail.com> X-Mailer: git-send-email 1.7.9.5 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Kassey Li This adds support for spi interface sub device for soc_camera. Signed-off-by: Kassey Li --- drivers/media/platform/soc_camera/soc_camera.c | 51 ++++++++++++++++++++++++ include/media/soc_camera.h | 10 +++++ 2 files changed, 61 insertions(+) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index b3db51c..6db2d89 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1599,6 +1599,49 @@ static void scan_async_host(struct soc_camera_host *ici) #define soc_camera_i2c_free(icd) do {} while (0) #define scan_async_host(ici) do {} while (0) #endif +static int soc_camera_init_spi(struct soc_camera_device *icd, + struct soc_camera_desc *sdesc) +{ + struct spi_device *spi; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct soc_camera_host_desc *shd = &sdesc->host_desc; + struct spi_master *spi_master = + spi_busnum_to_master(shd->spi_bus_id); + struct v4l2_subdev *subdev; + + if (!spi_master) { + dev_err(icd->pdev, "Cannot get spi master #%d. No driver?\n", + shd->spi_bus_id); + goto espind; + } + + shd->board_info_spi->platform_data = &sdesc->subdev_desc; + + subdev = v4l2_spi_new_subdev(&ici->v4l2_dev, spi_master, + shd->board_info_spi); + if (!subdev) + goto espind; + + spi = v4l2_get_subdevdata(subdev); + + /* Use to_i2c_client(dev) to recover the i2c client */ + icd->control = &spi->dev; + + return 0; +espind: + return -ENODEV; +} + +static void soc_camera_free_spi(struct soc_camera_device *icd) +{ + struct spi_device *spi; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + + spi = v4l2_get_subdevdata(sd); + icd->control = NULL; + v4l2_device_unregister_subdev(sd); + spi_unregister_device(spi); +} #ifdef CONFIG_OF @@ -1762,6 +1805,10 @@ static int soc_camera_probe(struct soc_camera_host *ici, ret = soc_camera_i2c_init(icd, sdesc); if (ret < 0 && ret != -EPROBE_DEFER) goto eadd; + } else if (shd->board_info_spi) { + ret = soc_camera_init_spi(icd, sdesc); + if (ret < 0) + goto eadd; } else if (!shd->add_device || !shd->del_device) { ret = -EINVAL; goto eadd; @@ -1803,6 +1850,8 @@ static int soc_camera_probe(struct soc_camera_host *ici, efinish: if (shd->board_info) { soc_camera_i2c_free(icd); + } else if (shd->board_info_spi) { + soc_camera_free_spi(icd); } else { shd->del_device(icd); module_put(control->driver->owner); @@ -1843,6 +1892,8 @@ static int soc_camera_remove(struct soc_camera_device *icd) if (sdesc->host_desc.board_info) { soc_camera_i2c_free(icd); + } else if (sdesc->host_desc.board_info_spi) { + soc_camera_free_spi(icd); } else { struct device *dev = to_soc_camera_control(icd); struct device_driver *drv = dev ? dev->driver : NULL; diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 2f6261f..7530893 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -178,6 +178,11 @@ struct soc_camera_host_desc { int i2c_adapter_id; struct i2c_board_info *board_info; const char *module_name; + /* + * Add SPI device support. + */ + struct spi_board_info *board_info_spi; + int spi_bus_id; /* * For non-I2C devices platform has to provide methods to add a device @@ -243,6 +248,11 @@ struct soc_camera_link { int i2c_adapter_id; struct i2c_board_info *board_info; const char *module_name; + /* + * Add SPI device support. + */ + struct spi_board_info *board_info_spi; + int spi_bus_id; /* * For non-I2C devices platform has to provide methods to add a device