aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0880-Bluetooth-btbcm-Support-pcm-configuration.patch
blob: 2d40e7f5ac30c6c3855afa1384942acd8ca41936 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
From 6631d2076af26d2b5b6a3a2f17e8a33de48abcac Mon Sep 17 00:00:00 2001
From: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Date: Tue, 26 Nov 2019 08:17:30 +0100
Subject: [PATCH] Bluetooth: btbcm: Support pcm configuration

commit 528379902337102b0264fe5343eafb3d6c59fa45 upstream.

Add BCM vendor specific command to configure PCM parameters. The new
vendor opcode allows us to set the sco routing, the pcm interface rate,
and a few other pcm specific options (frame sync, sync mode, and clock
mode). See broadcom-bluetooth.txt in Documentation for more information
about valid values for those settings.

Here is an example trace where this opcode was used to configure
a BCM4354:

        < HCI Command: Vendor (0x3f|0x001c) plen 5
                01 02 00 01 01
        > HCI Event: Command Complete (0x0e) plen 4
        Vendor (0x3f|0x001c) ncmd 1
                Status: Success (0x00)

We can read back the values as well with ocf 0x001d to confirm the
values that were set:
        $ hcitool cmd 0x3f 0x001d
        < HCI Command: ogf 0x3f, ocf 0x001d, plen 0
        > HCI Event: 0x0e plen 9
        01 1D FC 00 01 02 00 01 01

Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 drivers/bluetooth/btbcm.c | 46 +++++++++++++++++++++++++++++++++++++++
 drivers/bluetooth/btbcm.h | 16 ++++++++++++++
 2 files changed, 62 insertions(+)

--- a/drivers/bluetooth/btbcm.c
+++ b/drivers/bluetooth/btbcm.c
@@ -105,6 +105,52 @@ int btbcm_set_bdaddr(struct hci_dev *hde
 }
 EXPORT_SYMBOL_GPL(btbcm_set_bdaddr);
 
+int btbcm_read_pcm_int_params(struct hci_dev *hdev,
+			      struct bcm_set_pcm_int_params *params)
+{
+	struct sk_buff *skb;
+	int err = 0;
+
+	skb = __hci_cmd_sync(hdev, 0xfc1d, 0, NULL, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		err = PTR_ERR(skb);
+		bt_dev_err(hdev, "BCM: Read PCM int params failed (%d)", err);
+		return err;
+	}
+
+	if (skb->len != 6 || skb->data[0]) {
+		bt_dev_err(hdev, "BCM: Read PCM int params length mismatch");
+		kfree_skb(skb);
+		return -EIO;
+	}
+
+	if (params)
+		memcpy(params, skb->data + 1, 5);
+
+	kfree_skb(skb);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btbcm_read_pcm_int_params);
+
+int btbcm_write_pcm_int_params(struct hci_dev *hdev,
+			       const struct bcm_set_pcm_int_params *params)
+{
+	struct sk_buff *skb;
+	int err;
+
+	skb = __hci_cmd_sync(hdev, 0xfc1c, 5, params, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		err = PTR_ERR(skb);
+		bt_dev_err(hdev, "BCM: Write PCM int params failed (%d)", err);
+		return err;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btbcm_write_pcm_int_params);
+
 int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
 {
 	const struct hci_command_hdr *cmd;
--- a/drivers/bluetooth/btbcm.h
+++ b/drivers/bluetooth/btbcm.h
@@ -54,6 +54,10 @@ struct bcm_set_pcm_format_params {
 int btbcm_check_bdaddr(struct hci_dev *hdev);
 int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
 int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw);
+int btbcm_read_pcm_int_params(struct hci_dev *hdev,
+			      struct bcm_set_pcm_int_params *params);
+int btbcm_write_pcm_int_params(struct hci_dev *hdev,
+			       const struct bcm_set_pcm_int_params *params);
 
 int btbcm_setup_patchram(struct hci_dev *hdev);
 int btbcm_setup_apple(struct hci_dev *hdev);
@@ -73,6 +77,18 @@ static inline int btbcm_set_bdaddr(struc
 {
 	return -EOPNOTSUPP;
 }
+
+int btbcm_read_pcm_int_params(struct hci_dev *hdev,
+			      struct bcm_set_pcm_int_params *params)
+{
+	return -EOPNOTSUPP;
+}
+
+int btbcm_write_pcm_int_params(struct hci_dev *hdev,
+			       const struct bcm_set_pcm_int_params *params)
+{
+	return -EOPNOTSUPP;
+}
 
 static inline int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
 {
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
From 898198428aa35f52c2b58c037e960dcbcc4ef9d8 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 14 Apr 2020 16:12:33 +0100
Subject: [PATCH] media: i2c: ov9281: Fixup for recent kernel
 releases, and remove custom code

The Rockchip driver was based on a 4.4 kernel, and had several custom
Rockchip parts.

Update to 5.4 kernel APIs, with the relevant controls required by
libcamera, and remove custom Rockchip parts.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
 drivers/media/i2c/Kconfig  |   2 +-
 drivers/media/i2c/ov9281.c | 361 +++++++++++++------------------------
 2 files changed, 123 insertions(+), 240 deletions(-)

--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -857,7 +857,7 @@ config VIDEO_OV9640
 
 config VIDEO_OV9281
 	tristate "OmniVision OV9281 sensor support"
-	depends on I2C && VIDEO_V4L2
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
 	depends on MEDIA_CAMERA_SUPPORT
 	help
 	  This is a Video4Linux2 sensor-level driver for the OmniVision
--- a/drivers/media/i2c/ov9281.c
+++ b/drivers/media/i2c/ov9281.c
@@ -1,6 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * ov9281 driver
+ * Omnivision OV9281 1280x800 global shutter image sensor driver
+ *
+ * This driver has been taken from
+ * https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/media/i2c/ov9281.c
+ * cleaned up, made to compile against mainline kernels instead of the Rockchip
+ * vendor kernel, and the relevant controls added to work with libcamera.
  *
  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
  * V0.0X01.0X02 fix mclk issue when probe multiple camera.
@@ -17,22 +22,18 @@
 #include <linux/regulator/consumer.h>
 #include <linux/sysfs.h>
 #include <linux/slab.h>
-#include <linux/rk-camera-module.h>
 #include <media/media-entity.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-subdev.h>
-#include <linux/pinctrl/consumer.h>
-
-#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x3)
-
-#ifndef V4L2_CID_DIGITAL_GAIN
-#define V4L2_CID_DIGITAL_GAIN		V4L2_CID_GAIN
-#endif
 
 #define OV9281_LINK_FREQ_400MHZ		400000000
+#define OV9281_LANES			2
+#define OV9281_BITS_PER_SAMPLE		10
+
 /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
-#define OV9281_PIXEL_RATE		(OV9281_LINK_FREQ_400MHZ * 2 * 2 / 10)
+#define OV9281_PIXEL_RATE		(OV9281_LINK_FREQ_400MHZ * 2 * \
+					 OV9281_LANES / OV9281_BITS_PER_SAMPLE)
 #define OV9281_XVCLK_FREQ		24000000
 
 #define CHIP_ID				0x9281
@@ -63,18 +64,24 @@
 
 #define OV9281_REG_VTS			0x380e
 
+/*
+ * OV9281 native and active pixel array size.
+ * Datasheet not available to confirm these values, so assume there are no
+ * border pixels.
+ */
+#define OV9281_NATIVE_WIDTH		1280U
+#define OV9281_NATIVE_HEIGHT		800U
+#define OV9281_PIXEL_ARRAY_LEFT		0U
+#define OV9281_PIXEL_ARRAY_TOP		0U
+#define OV9281_PIXEL_ARRAY_WIDTH	1280U
+#define OV9281_PIXEL_ARRAY_HEIGHT	800U
+
 #define REG_NULL			0xFFFF
 
 #define OV9281_REG_VALUE_08BIT		1
 #define OV9281_REG_VALUE_16BIT		2
 #define OV9281_REG_VALUE_24BIT		3
 
-#define OV9281_LANES			2
-#define OV9281_BITS_PER_SAMPLE		10
-
-#define OF_CAMERA_PINCTRL_STATE_DEFAULT	"rockchip,camera_default"
-#define OF_CAMERA_PINCTRL_STATE_SLEEP	"rockchip,camera_sleep"
-
 #define OV9281_NAME			"ov9281"
 
 static const char * const ov9281_supply_names[] = {
@@ -93,10 +100,10 @@ struct regval {
 struct ov9281_mode {
 	u32 width;
 	u32 height;
-	struct v4l2_fract max_fps;
 	u32 hts_def;
 	u32 vts_def;
 	u32 exp_def;
+	struct v4l2_rect crop;
 	const struct regval *reg_list;
 };
 
@@ -107,10 +114,6 @@ struct ov9281 {
 	struct gpio_desc	*pwdn_gpio;
 	struct regulator_bulk_data supplies[OV9281_NUM_SUPPLIES];
 
-	struct pinctrl		*pinctrl;
-	struct pinctrl_state	*pins_default;
-	struct pinctrl_state	*pins_sleep;
-
 	struct v4l2_subdev	subdev;
 	struct media_pad	pad;
 	struct v4l2_ctrl_handler ctrl_handler;
@@ -124,23 +127,12 @@ struct ov9281 {
 	bool			streaming;
 	bool			power_on;
 	const struct ov9281_mode *cur_mode;
-	u32			module_index;
-	const char		*module_facing;
-	const char		*module_name;
-	const char		*len_name;
 };
 
 #define to_ov9281(sd) container_of(sd, struct ov9281, subdev)
 
 /*
  * Xclk 24Mhz
- */
-static const struct regval ov9281_global_regs[] = {
-	{REG_NULL, 0x00},
-};
-
-/*
- * Xclk 24Mhz
  * max_framerate 120fps
  * mipi_datarate per lane 800Mbps
  */
@@ -247,13 +239,15 @@ static const struct ov9281_mode supporte
 	{
 		.width = 1280,
 		.height = 800,
-		.max_fps = {
-			.numerator = 10000,
-			.denominator = 1200000,
-		},
 		.exp_def = 0x0320,
-		.hts_def = 0x0b60,//0x2d8*4
+		.hts_def = 0x05b0,	/* 0x2d8*2 */
 		.vts_def = 0x038e,
+		.crop = {
+			.left = 0,
+			.top = 0,
+			.width = 1280,
+			.height = 800
+		},
 		.reg_list = ov9281_1280x800_regs,
 	},
 };
@@ -389,22 +383,28 @@ static int ov9281_set_fmt(struct v4l2_su
 	fmt->format.width = mode->width;
 	fmt->format.height = mode->height;
 	fmt->format.field = V4L2_FIELD_NONE;
+	fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
+	fmt->format.ycbcr_enc =
+			V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace);
+	fmt->format.quantization =
+		V4L2_MAP_QUANTIZATION_DEFAULT(true, fmt->format.colorspace,
+					      fmt->format.ycbcr_enc);
+	fmt->format.xfer_func =
+		V4L2_MAP_XFER_FUNC_DEFAULT(fmt->format.colorspace);
+
 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
 		*v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
-#else
-		mutex_unlock(&ov9281->mutex);
-		return -ENOTTY;
-#endif
 	} else {
 		ov9281->cur_mode = mode;
 		h_blank = mode->hts_def - mode->width;
 		__v4l2_ctrl_modify_range(ov9281->hblank, h_blank,
 					 h_blank, 1, h_blank);
+		__v4l2_ctrl_s_ctrl(ov9281->hblank, h_blank);
 		vblank_def = mode->vts_def - mode->height;
 		__v4l2_ctrl_modify_range(ov9281->vblank, vblank_def,
 					 OV9281_VTS_MAX - mode->height,
 					 1, vblank_def);
+		__v4l2_ctrl_s_ctrl(ov9281->vblank, vblank_def);
 	}
 
 	mutex_unlock(&ov9281->mutex);
@@ -421,17 +421,21 @@ static int ov9281_get_fmt(struct v4l2_su
 
 	mutex_lock(&ov9281->mutex);
 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
 		fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
-#else
-		mutex_unlock(&ov9281->mutex);
-		return -ENOTTY;
-#endif
 	} else {
 		fmt->format.width = mode->width;
 		fmt->format.height = mode->height;
 		fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
 		fmt->format.field = V4L2_FIELD_NONE;
+		fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
+		fmt->format.ycbcr_enc =
+			V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace);
+		fmt->format.quantization =
+			V4L2_MAP_QUANTIZATION_DEFAULT(true,
+						      fmt->format.colorspace,
+						      fmt->format.ycbcr_enc);
+		fmt->format.xfer_func =
+			V4L2_MAP_XFER_FUNC_DEFAULT(fmt->format.colorspace);
 	}
 	mutex_unlock(&ov9281->mutex);
 
@@ -442,7 +446,7 @@ static int ov9281_enum_mbus_code(struct
 				 struct v4l2_subdev_pad_config *cfg,
 				 struct v4l2_subdev_mbus_code_enum *code)
 {
-	if (code->index != 0)
+	if (code->index)
 		return -EINVAL;
 	code->code = MEDIA_BUS_FMT_Y10_1X10;
 
@@ -480,88 +484,56 @@ static int ov9281_enable_test_pattern(st
 				OV9281_REG_VALUE_08BIT, val);
 }
 
-static int OV9281_g_frame_interval(struct v4l2_subdev *sd,
-				   struct v4l2_subdev_frame_interval *fi)
-{
-	struct ov9281 *ov9281 = to_ov9281(sd);
-	const struct ov9281_mode *mode = ov9281->cur_mode;
-
-	mutex_lock(&ov9281->mutex);
-	fi->interval = mode->max_fps;
-	mutex_unlock(&ov9281->mutex);
+static const struct v4l2_rect *
+__ov9281_get_pad_crop(struct ov9281 *ov9281, struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(&ov9281->subdev, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &ov9281->cur_mode->crop;
+	}
 
-	return 0;
+	return NULL;
 }
 
-static void ov9281_get_module_inf(struct ov9281 *ov9281,
-				  struct rkmodule_inf *inf)
+static int ov9281_get_selection(struct v4l2_subdev *sd,
+				struct v4l2_subdev_pad_config *cfg,
+				struct v4l2_subdev_selection *sel)
 {
-	memset(inf, 0, sizeof(*inf));
-	strlcpy(inf->base.sensor, OV9281_NAME, sizeof(inf->base.sensor));
-	strlcpy(inf->base.module, ov9281->module_name,
-		sizeof(inf->base.module));
-	strlcpy(inf->base.lens, ov9281->len_name, sizeof(inf->base.lens));
-}
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP: {
+		struct ov9281 *ov9281 = to_ov9281(sd);
 
-static long ov9281_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
-{
-	struct ov9281 *ov9281 = to_ov9281(sd);
-	long ret = 0;
+		mutex_lock(&ov9281->mutex);
+		sel->r = *__ov9281_get_pad_crop(ov9281, cfg, sel->pad,
+						sel->which);
+		mutex_unlock(&ov9281->mutex);
 
-	switch (cmd) {
-	case RKMODULE_GET_MODULE_INFO:
-		ov9281_get_module_inf(ov9281, (struct rkmodule_inf *)arg);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
+		return 0;
 	}
 
-	return ret;
-}
+	case V4L2_SEL_TGT_NATIVE_SIZE:
+		sel->r.top = 0;
+		sel->r.left = 0;
+		sel->r.width = OV9281_NATIVE_WIDTH;
+		sel->r.height = OV9281_NATIVE_HEIGHT;
 
-#ifdef CONFIG_COMPAT
-static long ov9281_compat_ioctl32(struct v4l2_subdev *sd,
-				  unsigned int cmd, unsigned long arg)
-{
-	void __user *up = compat_ptr(arg);
-	struct rkmodule_inf *inf;
-	struct rkmodule_awb_cfg *cfg;
-	long ret;
-
-	switch (cmd) {
-	case RKMODULE_GET_MODULE_INFO:
-		inf = kzalloc(sizeof(*inf), GFP_KERNEL);
-		if (!inf) {
-			ret = -ENOMEM;
-			return ret;
-		}
+		return 0;
 
-		ret = ov9281_ioctl(sd, cmd, inf);
-		if (!ret)
-			ret = copy_to_user(up, inf, sizeof(*inf));
-		kfree(inf);
-		break;
-	case RKMODULE_AWB_CFG:
-		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
-		if (!cfg) {
-			ret = -ENOMEM;
-			return ret;
-		}
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		sel->r.top = OV9281_PIXEL_ARRAY_TOP;
+		sel->r.left = OV9281_PIXEL_ARRAY_LEFT;
+		sel->r.width = OV9281_PIXEL_ARRAY_WIDTH;
+		sel->r.height = OV9281_PIXEL_ARRAY_HEIGHT;
 
-		ret = copy_from_user(cfg, up, sizeof(*cfg));
-		if (!ret)
-			ret = ov9281_ioctl(sd, cmd, cfg);
-		kfree(cfg);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
+		return 0;
 	}
 
-	return ret;
+	return -EINVAL;
 }
-#endif
 
 static int __ov9281_start_stream(struct ov9281 *ov9281)
 {
@@ -643,12 +615,6 @@ static int ov9281_s_power(struct v4l2_su
 			pm_runtime_put_noidle(&client->dev);
 			goto unlock_and_return;
 		}
-		ret = ov9281_write_array(ov9281->client, ov9281_global_regs);
-		if (ret) {
-			v4l2_err(sd, "could not set init registers\n");
-			pm_runtime_put_noidle(&client->dev);
-			goto unlock_and_return;
-		}
 		ov9281->power_on = true;
 	} else {
 		pm_runtime_put(&client->dev);
@@ -673,18 +639,12 @@ static int __ov9281_power_on(struct ov92
 	u32 delay_us;
 	struct device *dev = &ov9281->client->dev;
 
-	if (!IS_ERR_OR_NULL(ov9281->pins_default)) {
-		ret = pinctrl_select_state(ov9281->pinctrl,
-					   ov9281->pins_default);
-		if (ret < 0)
-			dev_err(dev, "could not set pins\n");
-	}
-
 	ret = clk_set_rate(ov9281->xvclk, OV9281_XVCLK_FREQ);
 	if (ret < 0)
 		dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
 	if (clk_get_rate(ov9281->xvclk) != OV9281_XVCLK_FREQ)
-		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
+		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz - rate is %lu\n",
+			 clk_get_rate(ov9281->xvclk));
 
 	ret = clk_prepare_enable(ov9281->xvclk);
 	if (ret < 0) {
@@ -722,20 +682,11 @@ disable_clk:
 
 static void __ov9281_power_off(struct ov9281 *ov9281)
 {
-	int ret;
-	struct device *dev = &ov9281->client->dev;
-
 	if (!IS_ERR(ov9281->pwdn_gpio))
 		gpiod_set_value_cansleep(ov9281->pwdn_gpio, 0);
 	clk_disable_unprepare(ov9281->xvclk);
 	if (!IS_ERR(ov9281->reset_gpio))
 		gpiod_set_value_cansleep(ov9281->reset_gpio, 0);
-	if (!IS_ERR_OR_NULL(ov9281->pins_sleep)) {
-		ret = pinctrl_select_state(ov9281->pinctrl,
-					   ov9281->pins_sleep);
-		if (ret < 0)
-			dev_dbg(dev, "could not set pins\n");
-	}
 	regulator_bulk_disable(OV9281_NUM_SUPPLIES, ov9281->supplies);
 }
 
@@ -759,7 +710,6 @@ static int ov9281_runtime_suspend(struct
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
 static int ov9281_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
 	struct ov9281 *ov9281 = to_ov9281(sd);
@@ -773,61 +723,42 @@ static int ov9281_open(struct v4l2_subde
 	try_fmt->height = def_mode->height;
 	try_fmt->code = MEDIA_BUS_FMT_Y10_1X10;
 	try_fmt->field = V4L2_FIELD_NONE;
+	try_fmt->colorspace = V4L2_COLORSPACE_SRGB;
+	try_fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(try_fmt->colorspace);
+	try_fmt->quantization =
+		V4L2_MAP_QUANTIZATION_DEFAULT(true, try_fmt->colorspace,
+					      try_fmt->ycbcr_enc);
+	try_fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(try_fmt->colorspace);
 
 	mutex_unlock(&ov9281->mutex);
 	/* No crop or compose */
 
 	return 0;
 }
-#endif
-
-static int
-ov9281_enum_frame_interval(struct v4l2_subdev *sd,
-			   struct v4l2_subdev_pad_config *cfg,
-			   struct v4l2_subdev_frame_interval_enum *fie)
-{
-	if (fie->index >= ARRAY_SIZE(supported_modes))
-		return -EINVAL;
-
-	if (fie->code != MEDIA_BUS_FMT_Y10_1X10)
-		return -EINVAL;
-
-	fie->width = supported_modes[fie->index].width;
-	fie->height = supported_modes[fie->index].height;
-	fie->interval = supported_modes[fie->index].max_fps;
-	return 0;
-}
 
 static const struct dev_pm_ops ov9281_pm_ops = {
 	SET_RUNTIME_PM_OPS(ov9281_runtime_suspend,
 			   ov9281_runtime_resume, NULL)
 };
 
-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
 static const struct v4l2_subdev_internal_ops ov9281_internal_ops = {
 	.open = ov9281_open,
 };
-#endif
 
 static const struct v4l2_subdev_core_ops ov9281_core_ops = {
 	.s_power = ov9281_s_power,
-	.ioctl = ov9281_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl32 = ov9281_compat_ioctl32,
-#endif
 };
 
 static const struct v4l2_subdev_video_ops ov9281_video_ops = {
 	.s_stream = ov9281_s_stream,
-	.g_frame_interval = OV9281_g_frame_interval,
 };
 
 static const struct v4l2_subdev_pad_ops ov9281_pad_ops = {
 	.enum_mbus_code = ov9281_enum_mbus_code,
 	.enum_frame_size = ov9281_enum_frame_sizes,
-	.enum_frame_interval = ov9281_enum_frame_interval,
 	.get_fmt = ov9281_get_fmt,
 	.set_fmt = ov9281_set_fmt,
+	.get_selection = ov9281_get_selection,
 };
 
 static const struct v4l2_subdev_ops ov9281_subdev_ops = {
@@ -868,7 +799,8 @@ static int ov9281_set_ctrl(struct v4l2_c
 	case V4L2_CID_ANALOGUE_GAIN:
 		ret = ov9281_write_reg(ov9281->client, OV9281_REG_GAIN_H,
 				       OV9281_REG_VALUE_08BIT,
-				       (ctrl->val >> OV9281_GAIN_H_SHIFT) & OV9281_GAIN_H_MASK);
+				       (ctrl->val >> OV9281_GAIN_H_SHIFT) &
+							OV9281_GAIN_H_MASK);
 		ret |= ov9281_write_reg(ov9281->client, OV9281_REG_GAIN_L,
 				       OV9281_REG_VALUE_08BIT,
 				       ctrl->val & OV9281_GAIN_L_MASK);
@@ -922,31 +854,34 @@ static int ov9281_initialize_controls(st
 
 	h_blank = mode->hts_def - mode->width;
 	ov9281->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
-				h_blank, h_blank, 1, h_blank);
+					   h_blank, h_blank, 1, h_blank);
 	if (ov9281->hblank)
 		ov9281->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
 	vblank_def = mode->vts_def - mode->height;
 	ov9281->vblank = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
-				V4L2_CID_VBLANK, vblank_def,
-				OV9281_VTS_MAX - mode->height,
-				1, vblank_def);
+					   V4L2_CID_VBLANK, vblank_def,
+					   OV9281_VTS_MAX - mode->height, 1,
+					   vblank_def);
 
 	exposure_max = mode->vts_def - 4;
 	ov9281->exposure = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
-				V4L2_CID_EXPOSURE, OV9281_EXPOSURE_MIN,
-				exposure_max, OV9281_EXPOSURE_STEP,
-				mode->exp_def);
+					     V4L2_CID_EXPOSURE,
+					     OV9281_EXPOSURE_MIN, exposure_max,
+					     OV9281_EXPOSURE_STEP,
+					     mode->exp_def);
 
 	ov9281->anal_gain = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
-				V4L2_CID_ANALOGUE_GAIN, OV9281_GAIN_MIN,
-				OV9281_GAIN_MAX, OV9281_GAIN_STEP,
-				OV9281_GAIN_DEFAULT);
-
-	ov9281->test_pattern = v4l2_ctrl_new_std_menu_items(handler,
-				&ov9281_ctrl_ops, V4L2_CID_TEST_PATTERN,
-				ARRAY_SIZE(ov9281_test_pattern_menu) - 1,
-				0, 0, ov9281_test_pattern_menu);
+					      V4L2_CID_ANALOGUE_GAIN,
+					      OV9281_GAIN_MIN, OV9281_GAIN_MAX,
+					      OV9281_GAIN_STEP,
+					      OV9281_GAIN_DEFAULT);
+
+	ov9281->test_pattern =
+		v4l2_ctrl_new_std_menu_items(handler, &ov9281_ctrl_ops,
+					     V4L2_CID_TEST_PATTERN,
+					     ARRAY_SIZE(ov9281_test_pattern_menu) - 1,
+					     0, 0, ov9281_test_pattern_menu);
 
 	if (handler->error) {
 		ret = handler->error;
@@ -1000,34 +935,14 @@ static int ov9281_probe(struct i2c_clien
 			const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *node = dev->of_node;
 	struct ov9281 *ov9281;
 	struct v4l2_subdev *sd;
-	char facing[2];
 	int ret;
 
-	dev_info(dev, "driver version: %02x.%02x.%02x",
-		DRIVER_VERSION >> 16,
-		(DRIVER_VERSION & 0xff00) >> 8,
-		DRIVER_VERSION & 0x00ff);
-
 	ov9281 = devm_kzalloc(dev, sizeof(*ov9281), GFP_KERNEL);
 	if (!ov9281)
 		return -ENOMEM;
 
-	ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
-				   &ov9281->module_index);
-	ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
-				       &ov9281->module_facing);
-	ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
-				       &ov9281->module_name);
-	ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
-				       &ov9281->len_name);
-	if (ret) {
-		dev_err(dev, "could not get module information!\n");
-		return -EINVAL;
-	}
-
 	ov9281->client = client;
 	ov9281->cur_mode = &supported_modes[0];
 
@@ -1037,31 +952,15 @@ static int ov9281_probe(struct i2c_clien
 		return -EINVAL;
 	}
 
-	ov9281->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+	ov9281->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+						     GPIOD_OUT_LOW);
 	if (IS_ERR(ov9281->reset_gpio))
 		dev_warn(dev, "Failed to get reset-gpios\n");
 
-	ov9281->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
+	ov9281->pwdn_gpio = devm_gpiod_get_optional(dev, "pwdn", GPIOD_OUT_LOW);
 	if (IS_ERR(ov9281->pwdn_gpio))
 		dev_warn(dev, "Failed to get pwdn-gpios\n");
 
-	ov9281->pinctrl = devm_pinctrl_get(dev);
-	if (!IS_ERR(ov9281->pinctrl)) {
-		ov9281->pins_default =
-			pinctrl_lookup_state(ov9281->pinctrl,
-					     OF_CAMERA_PINCTRL_STATE_DEFAULT);
-		if (IS_ERR(ov9281->pins_default))
-			dev_err(dev, "could not get default pinstate\n");
-
-		ov9281->pins_sleep =
-			pinctrl_lookup_state(ov9281->pinctrl,
-					     OF_CAMERA_PINCTRL_STATE_SLEEP);
-		if (IS_ERR(ov9281->pins_sleep))
-			dev_err(dev, "could not get sleep pinstate\n");
-	} else {
-		dev_err(dev, "no pinctrl\n");
-	}
-
 	ret = ov9281_configure_regulators(ov9281);
 	if (ret) {
 		dev_err(dev, "Failed to get power regulators\n");
@@ -1084,26 +983,16 @@ static int ov9281_probe(struct i2c_clien
 	if (ret)
 		goto err_power_off;
 
-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
 	sd->internal_ops = &ov9281_internal_ops;
 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-#endif
-#if defined(CONFIG_MEDIA_CONTROLLER)
+
 	ov9281->pad.flags = MEDIA_PAD_FL_SOURCE;
-	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
-	ret = media_entity_init(&sd->entity, 1, &ov9281->pad, 0);
+	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+	ret = media_entity_pads_init(&sd->entity, 1, &ov9281->pad);
 	if (ret < 0)
 		goto err_power_off;
-#endif
-
-	memset(facing, 0, sizeof(facing));
-	if (strcmp(ov9281->module_facing, "back") == 0)
-		facing[0] = 'b';
-	else
-		facing[0] = 'f';
 
-	snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
-		 ov9281->module_index, facing,
+	snprintf(sd->name, sizeof(sd->name), "m%s %s",
 		 OV9281_NAME, dev_name(sd->dev));
 	ret = v4l2_async_register_subdev_sensor_common(sd);
 	if (ret) {
@@ -1118,9 +1007,7 @@ static int ov9281_probe(struct i2c_clien
 	return 0;
 
 err_clean_entity:
-#if defined(CONFIG_MEDIA_CONTROLLER)
 	media_entity_cleanup(&sd->entity);
-#endif
 err_power_off:
 	__ov9281_power_off(ov9281);
 err_free_handler:
@@ -1137,9 +1024,7 @@ static int ov9281_remove(struct i2c_clie
 	struct ov9281 *ov9281 = to_ov9281(sd);
 
 	v4l2_async_unregister_subdev(sd);
-#if defined(CONFIG_MEDIA_CONTROLLER)
 	media_entity_cleanup(&sd->entity);
-#endif
 	v4l2_ctrl_handler_free(&ov9281->ctrl_handler);
 	mutex_destroy(&ov9281->mutex);
 
@@ -1151,13 +1036,11 @@ static int ov9281_remove(struct i2c_clie
 	return 0;
 }
 
-#if IS_ENABLED(CONFIG_OF)
 static const struct of_device_id ov9281_of_match[] = {
 	{ .compatible = "ovti,ov9281" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ov9281_of_match);
-#endif
 
 static const struct i2c_device_id ov9281_match_id[] = {
 	{ "ovti,ov9281", 0 },