// STATUS (2024-11-25):
// - can't get an image
// - ov8858 shows up in `media-ctl -d 1 --print-topology`
// - imx258 doesn't show up in any `media-ctl` or `v4l2-ctl` commands, but does show in `modprobe` and `dmesg`
// - pmOS claims it should work in megapixels 2.x and snapshot/gnome camera: <https://wiki.postmarketos.org/wiki/PINE64_PinePhone_Pro_(pine64-pinephonepro)#Camera>
// - pmOS has IMX258 debugging info: <https://wiki.pine64.org/wiki/PinePhone_Pro/IMX258_Camera_Debugging>
//   - <https://elinux.org/images/9/94/ISP-presentation.pdf>
//
// STATUS (2024-11-29):
// - megapixels-next can preview and capture the imx258 rear camera!
// - this *requires* that ov8858 be fully disabled
//   not only ucam can't be enabled in DT, but even isp0 must be disabled else the pipeline will try to render an (empty) ov8858!
// - disabling isp0 breaks pipewire; dmesg log spam: `rt5640 1-001c: ASoC: error at snd_soc_dai_set_sysclk on rt5640-aif1: -22`
//   however, this is due to a bug in nixpkgs' libcamera packaging
//   pull the fix and isp0 can be disabled w/o breaking pipewire: <https://github.com/NixOS/nixpkgs/pull/353336>
// - snapshot works, only if the libcamera + pipewire fix is pulled
//
//////////
// this is taken mostly verbatim from pine64-org / megi.
// only minimal checking against the datasheet.
// see pine64-org/linux commits:
// - 41742e56f573b90c002293a1d12d0e5ecee7ec87 for device-tree
// - 43243704827563df8410431da6d73ed25e379de8 for SCLK_CIF_OUT_SRC export (touches drivers/clk/rockchip/clk-rk3399.c)
//
// overview:
// - front cam: OV8858  (ucam = "user-facing camera" (i'm guessing))
// - rear cam: IMX258  (wcam = "world-facing camera")
// MIPI = Mobile Industry Processor Interface
// MIPI-DSI = MIPI Display Serial Interface
// MIPI-CSI = MIPI Camera Serial Interface
// - <https://en.wikipedia.org/wiki/Camera_Serial_Interface>
// - 1 clock lane + N data lanes  (PPP cameras use 4 data lanes)
// - each data line is two wires, because it uses differential signalling
// CCS = Camera Command Set
// - defines standard set of functionalities for CSI-2 devices
// DVP = Digital Video Port
//
// IMX258:
// - MIPI_RX0_D{0,1,2,3}{P,N}
// - MIPI_RX0_CLK{P,N}
// - MIPI_MCLK0
// - MIPI_RST0
// - DVP_PDN1_H1
// - I2C1_SDA
// - (I2C1_SCL)
// :: power:
// - VCC1V8_DVP
// - DVDD_DVP
// - VCC2V8_DVP
// - AVDD2V8_DVP
//
// OV8858:
// - identical wiring to IMC258, but uses MIPI 1 instead of MIPI 0.
// - uses same I2C1_{SDA,SCL}
// - uses same power rails
//
// - MIPI_MCLK0, MIPI_MCLK1 are tied to CIF_CLKO via 22ohm resistors
// - DVDD_DVP = VCC1V2_DVP
//
// STATUS:
// - power:
//   - [x] VCC1V8_DVP: enabled in mainline
//   - [?] DVDD_DVP (VCC1V2_DVP)
//   - [?] VCC2V8_DVP: PROBABLY enabled in mainline, as "vcc2v8_lcd"
//     other DTS files reference `vcc2v8_dvp`, but pine64-org's dts does *not*, nor does mainline's
//   - [?] AVDD2V8_DVP: NOT ENABLED
//     but seemingly not used in megi or pine64-org DTS

// for SCLK_CIF_OUT
#include <dt-bindings/clock/rk3399-cru.h>
// for GPIO_ACTIVE_LOW
#include <dt-bindings/gpio/gpio.h>
// for LED_FUNCTION_FLASH
#include <dt-bindings/leds/common.h>
// for RK_PA4, other pins
#include <dt-bindings/pinctrl/rockchip.h>

/dts-v1/;
/plugin/;

/ {
        /* ensure this overlay applies only to the correct board */
        compatible = "pine64,pinephone-pro";
};

&{/} {
       sgm3140: led-controller {
               compatible = "sgmicro,sgm3140";
               vin-supply = <&vcc3v3_sys>;
               pinctrl-names = "default";
               pinctrl-0 = <&flash_pins>;
               enable-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
               flash-gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;

               sgm3140_flash: led {
                       function = LED_FUNCTION_FLASH;
                       color = <LED_COLOR_ID_WHITE>;
                       flash-max-timeout-us = <250000>;
               };
       };
};

/* MEGI CLAIMS:
 * ============
 * Cameras:
 *
 * cif clk out = gpio2 B3 / CIF_CLKOUTA_u
 *
 * both on i2c1  GPIO4_A1 (SDA) / GPIO4_A2 (SCL)
 *
 * both share power:
 * VCC1V8_DVP         - LDO7  - supplied by VCC7 (VCC3V3_SYS)
 * DVDD_DVP     1.5V  - autoenabled by VCC2V8_DVP   depends on VCC1V8_S3 (U118 supplies 1.2V, though, not 1.5V)
 * VCC2V8_DVP   af    - autoenabled by VCC1V8_DVP   depends on VCC3V3_SYS
 * AVDD2V8_DVP        - autoenabled by VCC1V8_DVP   depends on VCC3V3_SYS
 *
 * isp1 = imx258
 *   reset = GPIO1_A0
 *   powerdown = GPIO2_B4
 *
 * isp0 = OV8858
 *   powerdown = GPIO2_D4
 *   reset = GPIO1_A4
 */
&i2c1 {
        status = "okay";

        clock-frequency = <400000>;
        i2c-scl-rising-time-ns = <300>;
        i2c-scl-falling-time-ns = <15>;

        // // rk3399-base.dtsi has:
        // //   assigned-clocks = <&cru SCLK_I2C1>;
        // //   assigned-clock-rates = <200000000>;
        // //   clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;
        // //   clock-names = "i2c", "pclk";
        // //   pinctrl-0 = <&i2c1_xfer>;
        // //   pinctrl-names = "default";
        pinctrl-0 = <&i2c1_xfer &cif_clkouta>;

        // // assigned-clocks = <&cru SCLK_CIF_OUT>;
        // // assigned-clock-rates = <19200000>;

        // // assigned-clocks = <&cru SCLK_I2C1 &cru SCLK_CIF_OUT &cru SCLK_CIF_OUT_SRC>;
        // // assigned-clock-parents = <&cru SCLK_I2C1 &cru SCLK_CIF_OUT_SRC &cru PLL_GPLL>;
        // // assigned-clock-rates = <200000000 19200000 0>;

        // // assigned-clocks = <&cru SCLK_I2C1>, <&cru SCLK_CIF_OUT>;
        // // assigned-clock-rates = <200000000>, <24000000>;
        // // assigned-clock-parents = <&cru SCLK_CIF_OUT_SRC>, <&cru PLL_GPLL>;

        // // // assigned-clocks = <&cru SCLK_CIF_OUT &cru SCLK_CIF_OUT_SRC>;
        // // // assigned-clock-parents = <&cru SCLK_CIF_OUT_SRC &cru PLL_GPLL>;
        // // // assigned-clock-rates = <19200000 0>;

        wcam: camera@1a {
                compatible = "sony,imx258";
                reg = <0x1a>;
                pinctrl-names = "default";
                pinctrl-0 = <&wcam_rst>;  //< megi (2024-05-25)
                // pinctrl-0 = <&wcam_rst &wcam_pdn>;  //< pine64-org

                clocks = <&cru SCLK_CIF_OUT>;
                clock-names = "xvclk";

                assigned-clocks = <&cru SCLK_CIF_OUT>;
                // nominal frequency seems to be 19200000, but driver complains that PPP can't actually generate a frequency that precise:
                // `imx258 1-001a: input clock frequency of 19161291 not supported`
                // assigned-clock-rates = <19200000>;
                assigned-clock-rates = <24000000>;

                vif-supply = <&vcc1v8_dvp>;
                i2c-supply = <&vcca1v8_codec>;
                /*XXX: also depends on vcca1v8_codec for I2C bus power (currently always on) */

                reset-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_LOW>;
                // powerdown-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>;  //< megi removed this (2024-05-25)

                orientation = <1>;
                rotation = <270>;

                lens-focus = <&wcam_lens>;
                flash-leds = <&sgm3140_flash>;

                port {
                        wcam_out: endpoint {
                                remote-endpoint = <&mipi_in_wcam>;
                                data-lanes = <1 2 3 4>;
                                // link frequencies = list of supported lane (?) frequencies.
                                // i believe this is defined in the camera driver:
                                // static const s64 link_freq_menu_items_19_2[] = {
                                //   633600000ULL,
                                //   320000000ULL,
                                // };
                                //
                                // static const s64 link_freq_menu_items_24[] = {
                                //   636000000ULL,
                                //   321000000ULL,
                                // };

                                link-frequencies = /bits/ 64 <636000000>;
                                // link-frequencies = /bits/ 64 <320000000 633600000>;
                                // link-frequencies = /bits/ 64 <321000000 636000000>;
                                // link-frequencies = /bits/ 64 <321000000>;
                        };
                };
        };

        wcam_lens: camera-lens@c {
                compatible = "dongwoon,dw9714";
                reg = <0x0c>;
                /*XXX: also depends on vcca1v8_codec for I2C bus power */
                vcc-supply = <&vcc1v8_dvp>;
        };

        // ucam: camera@36 {
        //         compatible = "ovti,ov8858";
        //         reg = <0x36>;
        //         pinctrl-names = "default";
        //         pinctrl-0 = <&ucam_pdn &ucam_rst>;

        //         clocks = <&cru SCLK_CIF_OUT>;
        //         clock-names = "xvclk";

        //         dovdd-supply = <&vcc1v8_dvp>;
        //         /*XXX: also depends on vcca1v8_codec for I2C bus power */

        //         reset-gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_LOW>;
        //         powerdown-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_LOW>;

        //         /* we're using forward ported BSP driver, thus: */
        //         rockchip,camera-module-index = <0x00>;
        //         rockchip,camera-module-facing = "front";
        //         rockchip,camera-module-name = "CameraKing";
        //         rockchip,camera-module-lens-name = "Largan-9569A2";

        //         orientation = <0>;
        //         rotation = <90>;

        //         port {
        //                 ucam_out: endpoint {
        //                         remote-endpoint = <&mipi_in_ucam>;
        //                         data-lanes = <1 2 3 4>;
        //                 };
        //         };
        // };
};

&pinctrl {
        camera {
                wcam_rst: wcam-rst {
                        rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
                // wcam_pdn: wcam-pdn {  //< megi removed this (2024-05-25)
                //         rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                // };

                ucam_rst: ucam-rst {
                        rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
                ucam_pdn: ucam-pdn {
                        rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
        leds {
                flash_pins: flash-pins {
                        rockchip,pins =
                                <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>,
                                <4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
};

&isp1 {
       status = "okay";

       ports {
               port@0 {
                       mipi_in_wcam: endpoint@0 {
                               reg = <0>;
                               remote-endpoint = <&wcam_out>;
                               data-lanes = <1 2 3 4>;
                       };
               };
       };
};

&mipi_dphy_rx0 {
       status = "okay";
};

// &isp0 {
//        status = "okay";
//
//        ports {
//                port@0 {
//                        mipi_in_ucam: endpoint@0 {
//                                reg = <0>;
//                                remote-endpoint = <&ucam_out>;
//                                data-lanes = <1 2 3 4>;
//                        };
//                };
//        };
// };

// &isp0_mmu {
//        status = "okay";
// };

&isp1_mmu {
       status = "okay";
};

&mipi_dsi1 {
       status = "okay";
};

// declared in rk3399-pinephone-pro.dts
// XXX(2024-11-28): i think these shouldn't *have* to be always-on:
//   imx258 should enable them when needed.
//   however, the patch which has imx258 actually enable its power supplies hasn't been upstreamed
&vcc1v8_dvp {
        // enable power to the regulator, always
        regulator-always-on;
        regulator-boot-on;
};
&vcc1v8_codec {
        // enable power to the regulator, always
        regulator-always-on;
        regulator-boot-on;
};
&vcca1v8_codec {
        // enable power to the regulator, always
        regulator-always-on;
        regulator-boot-on;
};
