From patchwork Tue Jan 27 02:40:07 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kassey Lee X-Patchwork-Id: 28053 X-Patchwork-Delegate: g.liakhovetski@gmx.de Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1YFw4e-00051y-7r; Tue, 27 Jan 2015 03:40:16 +0100 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.72/mailfrontend-8) with esmtp id 1YFw4a-0003Ip-m3; Tue, 27 Jan 2015 03:40:15 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755837AbbA0CkJ (ORCPT + 1 other); Mon, 26 Jan 2015 21:40:09 -0500 Received: from mail-we0-f170.google.com ([74.125.82.170]:43723 "EHLO mail-we0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751116AbbA0CkI (ORCPT ); Mon, 26 Jan 2015 21:40:08 -0500 Received: by mail-we0-f170.google.com with SMTP id w55so6988651wes.1 for ; Mon, 26 Jan 2015 18:40:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=ogovYj/ofViq0rj/NOjwcCzN2wfQu3lK5Mbx2lRx+gQ=; b=Rhd9QjBNojF6wGfTUrdQ6QaOInv8ElOAhp3QFocdro2+86btmyh2TgXX1ALNu6fLk4 nwTgN2C2Tr3Ap4UJerWOo+LcpnRoEuTEeTKFwQmR3lIN4KQ7qFdyYcxCqdSJHhiSSxuR rls24xLiOiCQNmWKed2ybfGBB8XbXYLUXqt/Jhygwe/pbU2R5t9CY2TqwemUTULTfcCH GE3SyG79UhfvL6drpKbGZG1GMuoqEAYnq7W5fQb10o37nQBiykEYPNr42PVIbmnb9mHj bjW0b9OvfPlcU4SO8jZc2GwFdkrJB6E93HZaHbP1Esj+pNNjN+yEEGdYSOB1IePcza+t wzdQ== MIME-Version: 1.0 X-Received: by 10.180.87.71 with SMTP id v7mr1315330wiz.28.1422326407114; Mon, 26 Jan 2015 18:40:07 -0800 (PST) Received: by 10.27.211.7 with HTTP; Mon, 26 Jan 2015 18:40:07 -0800 (PST) Date: Tue, 27 Jan 2015 10:40:07 +0800 Message-ID: Subject: [PATCH] [media] V4L: soc-camera: add SPI device support From: Kassey To: Guennadi Liakhovetski , Linux Media Mailing List , Kassey Li Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2015.1.27.23028 X-PMX-Spam: Gauge=IIIIIIIII, Probability=9%, Report=' FORGED_FROM_GMAIL 0.1, FROM_NAME_ONE_WORD 0.05, HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_4000_4999 0, BODY_SIZE_5000_LESS 0, BODY_SIZE_7000_LESS 0, CT_TEXT_PLAIN_UTF8_CAPS 0, DKIM_SIGNATURE 0, URI_ENDS_IN_HTML 0, WEBMAIL_SOURCE 0, __ANY_URI 0, __CP_URI_IN_BODY 0, __CT 0, __CT_TEXT_PLAIN 0, __DATE_TZ_HK 0, __FRAUD_WEBMAIL 0, __FRAUD_WEBMAIL_FROM 0, __FROM_GMAIL 0, __HAS_FROM 0, __HAS_MSGID 0, __HAS_X_MAILING_LIST 0, __MIME_TEXT_ONLY 0, __MIME_VERSION 0, __PHISH_SPEAR_HTTP_RECEIVED 0, __PHISH_SPEAR_STRUCTURE_1 0, __PHISH_SPEAR_STRUCTURE_2 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __URI_NO_WWW 0, __URI_NS , __YOUTUBE_RCVD 0' 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 | 11 +++++ 2 files changed, 62 insertions(+) -- 1.7.9.5 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..6d495f8 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -180,6 +180,12 @@ struct soc_camera_host_desc { 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 * to the system and to remove it */ @@ -243,6 +249,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